当你给Vue示例传递数据作为data时,你可能奇怪为什么当数据更新的时候,视图会跟随着数据一起更新?其实在Vue内部会进行数据劫持,即Vue遍历data对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
Object.defineProperty
Object.defineProperty可以用来定义一个对象的属性,不仅可以定义某个属性的值(value),也可以描述已有属性是否可枚举,是否可修改,定义setter和getter。如下:
let data={
title:"123"
}
Object.defineProperty(data,'title',{
value:'ss',
writable:true,// 允许重新改写
enumerable:true,// 可枚举,可以被for循环遍历到
configurable:true,// 可以被删除
})
Vue响应式的简单实现
利用Object.defineProperty,手写代码实现vue的数据劫持:
let data={
title:"123",
content:'666'
}
let title = document.getElementById("title");
let btn = document.getElementById("btn");
title.innerHTML=data.title;// 初次渲染更新模版
btn.onclick=function(){
data.title="321"; // 触发事件改变数据
// title.innerHTML="321"; // dom操作这样写,不仅要关注数据的变化,还要关注视图的更新
}
// 使用Object.defineProperty劫持数据,把属性转化成访问器的方式,getter获取时触发,setter设置时触发。
observer(data);
function observer(obj){
Object.keys(obj).forEach((item)=>{
defineReactive(obj,item,obj[item])
})
}
function defineReactive(obj,key,value){
Object.defineProperty(obj,key,{
get(){
return value;
},
set(newValue){
value=newValue;
title.innerHTML=newValue;// 简单实现,在setter中将数据给模版
}
})
}
Vue响应式原理图解:
如下图,当组件进行渲染时,发现模版中有动态数据需要添加,则触发该数据的getter获取数据,watcher在此时会记录下当前数据更新对应要更新的组件。
当某个时刻数据改变了,触发了该数据的setter,此时会通知watcher数据更新了,快去告诉那些依赖我的组件,然后对应组件更新重新渲染。
vue响应式原理
网友评论