Vue2

收获

  • 在实例化 Vue 对象时,data 属性所引用的 data 对象的属性,在实例时就固定下来了;即如果后续给 data 对象添加的新属性,并不会出现在 Vue 对象中;
  • 在 HTML 标签上可以使用 v-bind 等指令,来将某个标签的属性值和某个 vue 对象的属性值进行绑定;
  • 在 input 标签上使用 v-model 指令,可以实现在输入框中,对 vue 对象属性值的修改,从而实现双向绑定;
  • 组件绑定的对象,如果使用了 Object.freeze 方法处理过,则绑定将失效,即对象属性的更新,将不再会反应到视图上面;

生命周期钩子

Vue 实例由若干个阶段组成它的生命周期,它带来一些内置的方法,可以在这些阶段插入一些想要实现的函数,即所谓的钩子,包括 created、mounted、updated、destroyed 等;

模板语法

插值

文本

用双大括号绑定 Vue 实例的 data;如果在 HTML 标签上添加 v-once 属性,则插值只会赋值一次,之后不会动态更新;

1
2
3
<span>Message: {{ msg }}</span>

<span v-once>这个将不会改变: {{ msg }}</span>
原始 HTML

当 Vue 实例的 data 不是普通的字符串,而是原始 html 格式字符串时,如果使用常规的双大括号,这些 html 格式的字符串,将被当成普通的文本处理;此时需要改成给标签增加 v-html 属性来绑定值,它才会被当作 HTML 处理;

1
2
3
<p>Using mustaches: {{ rawHtml }}</p> 

<p>Using v-html directive: <span v-html="rawHtml"></span></p>
Attribute

双大括号的写法,无法将 data 值赋给 HTML 标签的属性,此时需要使用 v-bind 指令来达到预期效果

1
2
3
<div v-bind:id="dynamicId"></div>
<!---或者也可以直接写成如下格式--->
<div :id="dynamicId"></div>
使用 javascript 表达式

在双大括号的内部,除了给绑定 data 值外,也是可以使用 javascript 表达式的;

1
2
3
4
5
6
7
{{ number + 1 }} 

{{ ok ? 'YES' : 'NO' }}

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

<div v-bind:id="'list-' + id"></div>

指令

“指令”指的是在 HTML 标签中使用 v- 前缀的特殊属性;除了 v-for 外,指令的值应为单个 javascript 表达式;它的作用是当表达式的值发生改变时,能够将新值作用于 DOM 元素,使其产生预期的变化;

1
<p v-if="seen">现在你看到我了</p>
参数

有些指令能够接收参数,用来将表达式与参数所代表的属性值或者事件进行绑定

1
2
3
<a v-bind:href="url">...</a>

<a v-on:click="doSomething">...</a>
动态参数

参数早期是一个静态的字符串,如果想让它变成动态的,则可以通过增加中括号来实现;这个时候参数实际上是一个表达式,通过表达式的求值,获得绑定目标,一般来说,这个目标应该是字符串类型的值,除了 null 外,其他非字符串的结果都会引发错误;

另外表达式存在一些约束,例如不能使用空格或者引号、不能使用大写字符来定义键名(会被强制转化小写,可能导致表达式求值失败);

1
<a v-bind:[attributeName]="url"> ... </a>
修饰符

指令允许接以点号为标记的后缀,用来表达该指令需要以特殊的方式进行绑定;

例如:.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault():

1
<form v-on:submit.prevent="onSubmit">...</form>

缩写

v-bind 缩写

1
2
3
4
5
6
7
8
<!-- 完整语法 --> 
<a v-bind:href="url">...</a>

<!-- 缩写 -->
<a :href="url">...</a>

<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>

v-on 缩写

1
2
3
4
5
6
7
8
<!-- 完整语法 --> 
<a v-on:click="doSomething">...</a>

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

<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>

计算属性和侦听器

双大括号适合用来放置一些简单的变量,虽然它也支持内置表达式,但是如果表达式很长,或者逻辑比较复杂,则看起来比较困难,此时可以使用 Vue 实例中的 computed 属性,在这个属性中,同样可以内置变量,但这些变量实际上是函数,当 HTML 标签绑定到这些变量后,它实际上是会执行函数并将最终结果赋值给标签;

1
2
3
4
<div id="example"> 
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
1
2
3
4
5
6
7
8
9
10
11
var vm = new Vue({ 
el: '#example',
data: { message: 'Hello' },
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('');
}
}
});

计算属性 vs 方法

事实上,前面的例子,也可以通过给 HTML 标签绑定 Vue 实例的方法来实现;

1
<p>Reversed message: "{{ reversedMessage( ) }}"</p>
1
2
3
4
5
6
7
var vm = new Vue({
methods: {
reverseMessage: function () {
return this.message.split('').reverse().join('');
}
}
});

虽然二者的结果是相同的,但是背后却有所区别;如果是绑定 Vue 实例的方法,每次访问变量,都会执行方法计算结果;但计算属性则使用缓存来返回结果,直到所绑定的标签发生变化后,才会重新求值,因此它的性能更加好;对于简单的计算二者区别不明显,但是如果计算量很大,则可能产生明显差别;

计算属性 vs 监听属性

监听属性可以用来监听 data 中的属性值变化,当发生变化时,就会调用提前写好的监听函数;当有某个变量是由多个其他变量合成的时候,则将该变量放置在计算属性中是更加简单的做法;

1
<div id="demo">{{ fullName }}</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 监听属性的做法
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
// 计算属性的做法
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName;
}
}
});

计算属性的 setter

计算属性默认只有 getter,但其实它也支持 setter 的做法;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
computed: { 
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}

侦听器

可以用来监听实例 data 属性中某个变量值的变化;当监听到某个变量值变化时,相应的函数就会被触发;大多数情况下使用计算属性更合适,但偶尔有时候,使用侦听属性更方便;监听器特别适合用来执行一些异步或计算开销大的函数;

1
2
3
4
<div id="watch-example"> 
<p> Ask a yes/no question: <input v-model="question"> </p>
<p>{{ answer }}</p>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var watchExampleVM = new Vue({ 
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...';
this.debouncedGetAnswer();
}
},
created: function () {
// 初始化时,调用 lodash 的 denounce,生成一个限制频率的新函数;
this.denounceGetAnswer = _.denounce(this.getAnswer, 500);
},
methods: {
getAnswer: funcion () {
this.answer = 'Thinking...'
var vm = this;
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer) })
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
});
}
}
});

Class 与 Style 绑定

绑定 HTML class

使用 v-bind 进行表达式与属性的绑定时,表达式的计算结果是字符串,多数情况下这是OK的,但是如果是要动态的改变 CSS 的 Class 时,拼接字符串就显得麻烦而且容易出错;此时可以通过给 v-bind:class 传递一个对象,来实现对 CSS Class 的动态增加和减少(即让 HTML 是否拥有哪几个 Class);

1
2
3
<div v-bind:class="{ active: isActive }"></div>
<!-- 当 isActive 的值为 true 时,div 就拥有 active 类,等同如下写法,否则没有 -->
<div class="active"></div>

另外上面的例子,还可以写成如下的样子

1
<div v-bind:class="classObj"></div>
1
2
3
4
5
6
7
var vm = new Vue({
data: {
classObj: {
active: isActive
}
}
});

甚至 classObj 还可以放在计算属性中,实现更高级和复杂的场景;

1
<div v-bind:class="classObj"></div>
1
2
3
4
5
6
7
8
9
10
data: {
isActive: true
},
computed: {
classObj: function () {
return {
active: this.isActive
}
}
}
数组语法

除了对象外,v-bind:class 还支持数组类型的值,以实现同时绑定多个 class

1
<div v-bind:class="[activeClass, errorClass]"></div>
1
2
3
4
data: { 
activeClass: 'active',
errorClass: 'text-danger'
}
用在组件上

在定义组件时,允许在 template 上面提前写入一些 class,之后在引用组件时,还可以再定义 class,此时的定义不会覆盖前面的定义;

1
2
3
Vue.component('my-component', { 
template: '<p class="foo bar">Hi</p>'
});
1
<my-component class="baz boo"></my-component>

最终的渲染结果如下:

1
<p class="foo bar baz boo">Hi</p>

绑定内联样式

对象语法
1
<div v-bind:style="styleObject"></div>
1
2
3
4
5
6
7
// 除了绑定 data,也可以绑定计算属性 computed
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
数组语法
1
<div v-bind:style="[baseStyles, overridingStyles]"></div>
自动添加前缀

如果某些 CSS 样式需要根据不同的浏览器格式要求,添加相应的前缀,例如 transform,该工作会由 Vue 自动侦测并处理;

多重值

支持数组提供多个备用值,Vue 会自动检查哪个值适用,如果都不适用,则使用最后那一个;

1
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

条件渲染

v-if

1
2
<h1 v-if="awesome">Vue is awesome!</h1> 
<h1 v-else>Oh no 😢</h1>

如果需要对多个 HTML 元素实现条件切换,则可以使用