一、实例的生命周期钩子
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
1、生命周期图示
2、钩子函数触发的时间
beforeCreate
:
在实例初始化之后,数据观测(data observer
) 和 event/watcher 事件配置之前被调用。
created
:
实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el
属性目前不可见。
beforeMount
:
在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted
:
el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
beforeUpdate
:
数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
updated
:
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。
该钩子在服务器端渲染期间不被调用。
beforeDestroy
:
实例销毁之前调用。在这一步,实例仍然完全可用。
可以在组件卸载之前进行数据缓存等操作。
destroyed
:
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
二、计算属性 和 侦听器
1、计算属性
你可以像绑定普通 property 一样在模板中绑定计算属性,如下例中的{{ reversedMessage }}
。(所以计算属性的 getter 方法 必须带返回值)
比如:
HTML代码:
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
JavaScript代码;
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
Vue 知道
vm.reversedMessage
依赖于vm.message
,因此当vm.message
发生改变时,所有依赖vm.reversedMessage
的绑定也会更新。
computed 和 methods 的区别:
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。
然而,不同的是计算属性是基于它们的响应式依赖进行缓存的(可以缓存上一次的值)。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
计算属性的setter:
计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:
// ...
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]
}
}
}
// ...
现在再运行
vm.fullName = 'John Doe'
时,setter 会被调用,vm.firstName
和vm.lastName
也会相应地被更新。
2、侦听属性 watch
观察和响应 Vue 实例上的数据变动。
watch 监听属性上的回调函数,在监听的数据发生变化时被调用。回调函数接收两个参数oldvalue,value。
watch:{
//变量msg发生变化时执行
msg(oldvalue,value){
console.log(old,value)
}
}
注意:
当你有一些数据需要随着其它数据变动而变动时,通常更好的做法是使用计算属性而不是命令式的 watch 回调。
因为当该数据依赖于多个数据变动时,使用watch
侦听属性,代码往往会变得重复(需要同时监听多个数据变化),而使用计算属性,则会避免代码重复的问题(多个数据可以放在同一个计算属性方法里边操作,返回操作结果)。如下:
HTML代码:
<div id="demo">{{ fullName }}</div>
使用侦听属性:
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
}
}
})
使用计算属性:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
3、侦听器
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时 执行异步或开销较大的操作时,这个方式是最有用的。