一、如何追踪变化
使用Object.defineProperty
将传入的属性转换为setter/getter
。每个组件实例有相应的 watcher
实例对象,会在组件渲染时将属性记录为依赖,当相关依赖的setter
被调用时,会通知watcher
重新计算更新组件。
总结:每个实例有watcher
监听变化,属性和实例之间通过Object.defineProperty
方法转换。
二、检测变化的注意事项
vue不能检测到对象属性的添加或删除。
所以vue在初始化实例对属性进行setter/getter
转换过程时,属性必须在data
对象上,才能做到响应式。
var vm = new Vue({
data:{//初始化必须在data中
a:1
}
})
// `vm.a` 是响应的
vm.b = 2
// `vm.b` 是非响应的
添加新的属性:
Vue.set(vm.Object,key,value)//方法一
this.$set(this.Object,key,value)//方法二
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
//方法三,创建新的对象,包含元对象的属性和新的属性。
三、声明响应式属性(提前声明所有的响应式属性)
由于Vue不允许动态添加响应式属性,所以必须在初始化实例前声明根基响应式属性,哪怕是空值。
data:{message:''}
如果在data
中未声明message
,vue将警告渲染函数在是试图访问的属性不存在(遇到好多次了)。
总结:vue不能动态更新根属性,属性需要提前声明,才能响应式,可以添加属性同步响应式。
四、异步更新队列(DOM实时更新)
当watcher
被触发时,数据不是立即变化重新渲染,而是推入队列中,当刷新队列时重新渲染。避免直接操作dom,又不得不操作时(比如echart图表)使用Vue.nextTick(callback)
方法。回调函数在DOM更新完成后调用。在组件中自动绑定当前的Vue事例中。
Vue.component('example', {
template: '<span>{{ message }}</span>',
data: function () {
return {
message: '没有更新'
}
},
methods: {
updateMessage: function () {
this.message = '更新完成'
console.log(this.$el.textContent) // => '没有更新'
this.$nextTick(function () {
console.log(this.$el.textContent) // => '更新完成'
})
}
}
})