前端学习总结(二十一)Vue.js——博采众长的后起之秀

时间:2021-01-22 19:15:15

Vue概述

实质:构建数据驱动的 web 界面的库

目标:通过尽可能简单的 API 实现响应的数据绑定组合的视图组件

特点:

只聚焦于视图层,简单易于学习,容易与其它库或已有项目整合。

在与相关工具和支持库一起使用时,能完美地驱动复杂的单页应用。

Vue和其他技术的对比

VS Angular:

1.比 Angular 简单得多,可以快速掌握

2.更加灵活开放,允许以希望的方式组织应用程序,而不是任何时候都遵循 Angular 的规则。仅仅是一个视图层,可以嵌入到一个现有页面而不一定要做成一个庞大的单页应用。

配合其他库方面有更大的的空间,但相应的也需要做更多的架构决策。如,Vue.js 核心默认不包含路由和 Ajax 功能,并通常假定在应用中使用一个模块构建系统。

3.Angular 使用双向绑定,Vue 也支持双向绑定,默认为单向绑定数据从父组件单向传给子组件。在大型应用中使用单向绑定让数据流易于理解

4.Vue中指令和组件分得更清晰指令只封装 DOM 操作,而组件代表一个自给自足的独立单元 —— 有自己的视图和数据逻辑。在 Angular 中两者有不少相混的地方。

5.Vue有更好的性能,且非常容易优化,因为它不使用脏检查。*Angular,当 watcher 越来越多时会变得越来越慢,因为作用域内的每一次变化,所有 watcher 都要重新计算。并且,如果一些 watcher 触发另一个更新,脏检查循环可能要运行多次*。

Angular 用户常常要使用深奥的技术,以解决脏检查循环的问题。有时没有简单的办法来优化有大量 watcher 的作用域。Vue.js 则根本没有这个问题,因为它使用基于依赖追踪的观察系统并且异步列队更新,所有的数据变化都是独立地触发,除非它们之间有明确的依赖关系。唯一需要的优化是在 v-for 上使用 track-by。

而Angular 2 和 Vue 用相似的设计解决了一些 Angular 1 中存在的问题。

VS React

同:都提供数据驱动、可组合搭建的视图组件。

异:

1.内部实现本质不同。React 的渲染建立在 Virtual DOM 上——一种在内存中描述 DOM 树状态的数据结构。当状态发生变化时,React 重新渲染 Virtual DOM,比较计算之后给真实 DOM 打补丁

2.Virtual DOM 提供了函数式的方法描述视图,它不使用数据观察机制,每次更新都会重新渲染整个应用,因此从定义上保证了视图与数据的同步。它也开辟了 JavaScript 同构应用的可能性。

3.Vue.js 不使用 Virtual DOM 而是使用真实 DOM 作为模板,数据绑定到真实节点。Vue.js 的应用环境必须提供 DOM。但是,相对于常见的误解——Virtual DOM 让 React 比其它的都快, Vue.js 实际上性能比 React 好,而且几乎不用手工优化。而* React,为了最优化的渲染需要处处实现 shouldComponentUpdate 和使用不可变数据结构*

4.在 API 方面,React(或 JSX)的一个问题是,渲染函数常常包含大量的逻辑,最终看着更像是程序片断而不是界面的视觉呈现。对于部分开发者来说,他们可能觉得这是个优点,但对那些像我一样兼顾设计和开发的人来说,模板能让我们更好地在视觉上思考设计和 CSS。JSX 和 JavaScript 逻辑的混合干扰了我将代码映射到设计的思维过程。相反,Vue.js 通过在模板中加入一个轻量级的 DSL (指令系统),换来一个依旧直观的模板,且能将逻辑封装进指令和过滤器中。

5.React 的另一个问题是:DOM 更新完全交给 Virtual DOM,想要自己控制 DOM 时就比较棘手。如果应用需要特别的自定义 DOM 操作,特别是复杂时间控制的动画,这个限制就很讨厌。在这方面,Vue.js 更灵活。

React的函数式特质,可以很好地使用函数式编程模式。但是对于初级开发者和初学者这也导致较大的学习难度。Vue 更易学习和开发。

对于大型应用,React 社区已经创造了大量的状态管理方案,如 Flux/Redux。Vue 本身不解决这个问题,但是可以轻松地修改状态管理模式,实现一个类似的架构。Vue 有自己的状态管理方案 Vuex,而且 Vue 也可以与 Redux 一起用

Vue 的 单文件组件 在把 CSS 封装到组件模块的同时仍然允许你使用喜欢的预处理器。

Vue 实例

创建Vue实例:

每个 Vue 应用的起步都是通过构造函数 Vue() 创建 Vue 的根实例:

var vm = new Vue({
// 选项
})

一个 Vue 实例是一个ViewModel (MVVM 模式) 。

在实例化 Vue 时,要传入一个选项对象,它可以包含数据、模板、挂载元素、方法、生命周期钩子等选项。

Vue实例的属性与方法

1.数据属性

每个 Vue 实例都会代理其 data 对象里所有的属性

var data = { a: 1 }
var vm = new Vue({
el:'id1', //el:绑定id
data: data //data:绑定数据
})

vm.a === data.a // -> true vm实例的数据与其data所绑定的对象的数据是保持一致的

只有这些被代理的属性是响应的。在实例创建之后添加新的属性到实例上不会触发视图更新。

注意只有这些被代理的属性是响应的。如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。我们将在后面详细讨论响应系统。

2.其他属性与方法

除了data属性代理数据,Vue 实例暴露了一些有用的实例属性与方法。这些属性与方法都有前缀 $ ,如:

var data = { a: 1 }
var vm = new Vue({
el: '#example',
data: data
})

vm.$data === data // Vue实例对象.$data 绑定了数据
vm.$el === document.getElementById('example') // .$el绑定了id

// $watch 是一个实例方法,当Vue实例的某属性改变后触发回调函数
vm.$watch('a', function (newVal, oldVal) {
// 这个回调在 `vm.a` 改变后调用
})

Vue实例的生命周期

Vue 实例在创建时有一系列初始化步骤,它也将调用一些生命周期钩子,给自定义逻辑提供运行机会。例如 created 钩子在实例创建后调用:

var vm = new Vue({
data: {
a: 1
},
created: function () { //注意这个函数
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})

也有一些其它的钩子,在实例生命周期的不同阶段调用,如 compiled、 ready 、destroyed。钩子的 this 指向调用它的 Vue 实例。Vue.js 没有“控制器”的概念。组件的自定义逻辑可以分割在这些钩子中

数据绑定

Vue拥抱数据驱动的视图概念。即:在普通 HTML 模板中用特殊语法将 DOM “绑定”到底层数据。一旦创建绑定,DOM 将与数据保持同步。每当修改数据,DOM 便相应地更新。这样我们应用中的逻辑就几乎都是直接修改数据了,不必与 DOM 更新搅在一起。这让我们的代码更容易撰写、理解与维护

<!--1. 这是 View,即html-->
<div id="example-1">
Hello {{ name }}!
</div>
// 2.这是 Model,即数据量或数据对象
var exampleData = {
name: 'Vue.js'
}

// 3.这是Vue 实例(作为ViewModel)
// 它连接 View 与 Model
// 通过new Vue()创建,el绑定视图的id,data绑定data的数据
var exampleVM = new Vue({
el: '#example-1',
data: exampleData
})

DOM 会自动响应数据的变化。

Vue.js 模板通过一些特殊的特性做了html的增强。Vue 模板因而从根本上不同于基于字符串的模板。

绑定值

1.文本(双大括号绑定显示)

<span>Message: {{ msg }}</span>

每当这个属性变化时标签中显示的值也会更新。

如果只处理单次插值,今后的数据变化不想再引起插值更新,就在{{后加 *。

2.原始的 HTML

为输出 HTML 字符串,需要用{{{ }}}。

在网站上动态渲染任意 HTML 很危险,容易导致 XSS 攻击。记住,只对可信内容使用 HTML 插值,永不用于用户提交的内容

3.HTML 特性

{{}}也可以用在 HTML 特性内:

<div id="item-{{ id }}"></div>

注意: Vue.js 指令和特殊特性内不能用插值。

绑定 JS 表达式

用{{JS 表达式}},如:

{{ message.split('').reverse().join('') }}

每个绑定只能包含单个表达式,且不能绑定js语句。

过滤器

{{ message | 过滤器 }} //可接多个 | 过滤器

过滤器接受参数:

{{ message | filterA 'arg1' arg2 }}

过滤器函数始终以表达式的值作为第一个参数。后面跟的参数作为第2,3,…个参数。带引号的参数视为字符串,而不带引号的参数按表达式计算

指令

指令带有前缀 v-,以指示它们是 Vue.js 提供的特殊特性,它们会对绑定的目标元素添加响应式的特殊行为。

指令的值限定为绑定表达式,因此上面提到的 JavaScript 表达式及过滤器规则在这里也适用。

如:v-if

<div id="example-2">
<p v-if="greeting">Hello!</p>
</div>
var exampleVM2 = new Vue({
el: '#example-2',
data: {
greeting: true
}
})

指令绑定参数

有些指令可以名称后带一个“参数”,中间用冒号隔开。如,v-bind 指令用于响应地更新 HTML 特性

<a v-bind:href="url"></a>

这里 href 是参数,它告诉 v-bind 指令将元素的 href 特性跟表达式 url 的值绑定。用特性插值 href=”{{url}}” 能获得同样的结果。

再如 v-on 指令,它用于监听 DOM 事件:

<a v-on:click="doSomething">

这里参数是被监听的事件的名字。

修饰符

修饰符以半角句号 . 开始的特殊后缀,用于表示指令应当以特殊方式绑定。例如 .literal 修饰符告诉指令将它的值解析为一个字面字符串而不是一个表达式:

<a v-bind:href.literal="/a/b/c"></a>

指令缩写

Vue.js 为两个最常用的指令 v-bind 和 v-on 提供特别的缩写:

(1)v-bind缩写为冒号(:)

<!-- 完整语法 -->
<button v-bind:disabled="someDynamicCondition">Button</button>

<!-- 缩写 -->
<button :disabled="someDynamicCondition">Button</button>

(2)v-on: 缩写为 @

<!-- 完整语法 -->
<a v-on:click="doSomething"></a>

<!-- 缩写 -->
<a @click="doSomething"></a>

这些缩写用的多了还是能够提高编码效率的。

过渡

Vue指令不仅可以绑定 DOM 文本到数据,也可以绑定 DOM 结构 到数据。而且,Vue提供一个强大的过渡效果系统,可以在 Vue 插入/删除元素时自动应用过渡效果

通过 Vue.js 的过渡系统,可以在元素从 DOM 中插入或移除时自动应用过渡效果。Vue.js 会在适当的时机为你触发 CSS 过渡或动画,你也可以提供相应的 JavaScript 钩子函数在过渡过程中执行自定义 DOM 操作

为应用过渡效果,需要在目标元素上使用 transition 特性:

<div v-if="show" transition="my-transition"></div>

transition 特性可以与下面资源一起用:
v-if;
v-show;
v-for (只在插入和删除时触发,使用 vue-animated-list 插件);
动态组件 ;
在组件的根节点上,并且被 Vue 实例 DOM 方法(如 vm.$appendTo(el))触发;

当插入或删除带有过渡的元素时,Vue 将:

尝试以 ID “my-transition” 查找 JS 过渡钩子对象——通过 Vue.transition(id, hooks) 或 transitions 选项注册。如果找到,将在过渡的不同阶段调用相应的钩子。

自动嗅探目标元素是否有 CSS 过渡或动画,并在合适时添加/删除 CSS 类名。

如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作(插入/删除)在下一帧中立即执行

事件处理

用 v-on 指令监听 DOM 事件(v-on:事件名=“事件处理方法名”),如:

<div id="example">
<button v-on:click="greet">Greet</button>
</div>

这里的greet是事件处理器绑定的事件处理方法,在 Vue 实例中定义这个方法

var vm = new Vue({
el: '#example',
data: {
name: 'Vue.js'
},
// 在 `methods` 对象中定义方法
methods: {
greet: function (event) {
// 方法内 `this` 指向 vm
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
alert(event.target.tagName)
}
}
})

// 也可以在 JavaScript 代码中调用方法
vm.greet() // -> 'Hello Vue.js!'

除了直接绑定到一个方法,也可以在v-on 指令的值中使用内联 JavaScript 语句。

<div id="example-2">
<button v-on:click="say('hi')">Say Hi</button>
<button v-on:click="say('what')">Say What</button>
</div>
new Vue({
el: '#example-2',
methods: {
say: function (msg) {
alert(msg)
}
}
})

这里的say(‘hi’)就直接使用了js语句,并传入了参数。

组件

组件系统是 Vue的一个重要概念,它提供一种抽象,让我们可以用独立可复用的小组件构建大型应用

它是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。

一个典型的用 Vue 构建的大型应用可以抽象为一个组件树。

Vue.js 组件非常类似于 自定义元素—— Web 组件规范(即WebComponents)的一部分。Vue.js 的组件语法参考了该规范,但有几个关键的不同:

Web 组件规范仍远未完成,且没有浏览器实现。而Vue.js 组件不需要任何补丁,并且在所有支持的浏览器下表现一致。

Vue.js 组件提供了原生自定义元素所不具备的一些重要功能,比如组件间的数据流,自定义事件系统,以及动态的、带特效的组件替换。

注册组件

可以用 Vue.extend() 创建一个组件构造器

var MyComponent = Vue.extend({
// 选项...
})

要把这个构造器用作组件,需要用 Vue.component(tag, constructor) 注册

// 全局注册组件,tag 为 my-component
Vue.component('my-component', MyComponent)

注:对于自定义标签名,最好遵循 W3C 规则(小写,并包含一个短杠)。

组件在注册之后,便可以在父实例的模块中以自定义元素 如: 的形式使用

<div id="example">
<my-component></my-component>
</div>
// 定义
var MyComponent = Vue.extend({
template: '<div>A custom component!</div>'
})

// 注册
Vue.component('my-component', MyComponent)

// 创建根实例
new Vue({
el: '#example'
})

渲染的时候回渲染为:

<div id="example">
<div>A custom component!</div>
</div>

组件的模板会自动替换了自定义元素,自定义元素的作用只是作为一个挂载点。可以用实例选项 replace 决定是否替换。