很多学习过Vue2的小伙伴难以区分数据监测、数据代理、数据劫持这三个相近的概念,本文希望能够帮助大家理解和总结。
🤖 数据代理
1.1 何为数据代理
Vue中的数据代理就是通过vm对象来代理对data对象中属性的操作(读/写),它能够帮助我们更好地操作data中的数据。
1.2 Object.defineProperty()
要搞懂Vue数据代理这个概念,那我们就要从Object.defineProperty()入手,Object.defineProperty()是Vue中比较底层的一个方法,在数据劫持,数据代理以及计算属性等地方都或多或少的用到了此函数。
基本用法:
let person = {
name: '张三',
sex: '男'
}
//指定操作的对象、属性、配置对象
Object.defineProperty(person, 'age', {
// 当有人读取person的age属性时,get函数(getter)就会被调用,返回值就是age的值
get() {
console.log('有人读取age属性了');
return number
},
// 当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value) {
console.log('有人修改了age属性,且值是', value);
number = value
}
})
1.3 基本原理
- 通过
Object.defineProperty()把data对象中所有属性都添加到vm上 - 为每一个添加到vm上的属性,都指定一个
getter/setter - 在
getter/setter内部去操作(读/写)data中对应的属性
举个例子,当我们访问vm身上的name时,就会调用getter方法获取到data中的name;当我们修改vm身上的name时,就会调用setter方法修改data中的name,从而实现通过vm对象代理对data对象的操作。
🔪 数据劫持
2.1 何为数据劫持
利用JavaScript引擎赋予的功能,检测对象属性变化,即:利用js的API将data中的数据变为 发生变化可被监测的,通俗讲就是数据发生了变化,会被某个东西捕获到,这就是数据劫持。
2.2 基本原理
- Vue会监测到data中的所有属性,通过
Object.defineProperty()为每个属性进行加工,配上一套的getter、setter - 升级过后的data会被放置在vm身上的_data中,从而实现页面响应式更新
👀 数据监测
3.1 何为数据监测
Vue会监视data中所有层次的数据,当data中的数据发生改变时,Vue就会重新解析模板,更新界面。
3.2 基本原理
监测对象中的数据
通过setter实现监视,且要在new vue时就传入要监测的数据
(1). 对象中后追加的属性,Vue默认不做响应式处理
eg:vm._data.studnet.sex='女'
(2). 如需给后添加的属性做响应式,请使用以下API:
Vue.set(target, propertyName/index, value)
vm.$set(target, propertyName/index, value)
监测数组中的数据
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1). 调用原生对应的方法对数组进行更新。
(2). 重新解析模板,进而更新页面(基于Observer函数)。
注意:
- 直接增加或删除属性,视图不会更新;
- 通过数组索引修改元素,视图不会更新;
- 使用数组API或Vue.set()修改数组元素,视图会随之更新;
- Vue.set() 和 vm.$set() 不能给 vm 或 vm的根数据对象(vm._data) 添加属性。
💬 总结
数据劫持:加工data,为每个属性配上
getter和setter。
options.data -> vm._data
数据代理:通过vm代理对vm._data中属性的操作。
vm._data.xxx -> vm.xxx
数据监测:data中数据发生变化,模板中用到数据的相应位置发生响应式改变。
vm.xxx = 'newValue' -> 界面更新