0.回顾Object.defineProperty()方法
let number = 18let person = {name:'张三',sex:'男',}Object.defineProperty(person,'age',{// value:18,// enumerable:true, //控制属性是否可以枚举,默认值是false// writable:true, //控制属性是否可以被修改,默认值是false// configurable:true //控制属性是否可以被删除,默认值是false//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值get(){console.log('有人读取age属性了')return number},//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值set(value){console.log('有人修改了age属性,且值是',value)number = value}})
1.数据代理
- Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写) - Vue中数据代理的好处:
更加方便的操作data中的数据 - 基本原理:
- 通过Object.defineProperty()把data对象中所有属性添加到vm上。
- 为每一个添加到vm上的属性,都指定一个getter/setter。
- 在getter/setter内部去操作(读/写)data中对应的属性。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>何为数据代理</title></head><body><!-- 数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)--><script type="text/javascript" >let obj = {x:100}let obj2 = {y:200}Object.defineProperty(obj2,'x',{get(){return obj.x},set(value){obj.x = value}})</script></body>
</html>
2.数据劫持
定义一个Observer (数据的观察者),使用Object.defineProperty()来劫持各个属性,让数据对象的读写操作都处于自己的监管之下。
- 劫持一层数据结构的数据
//创建一个监视的实例对象,用于监视data中属性的变化const obs = new Observer(data) console.log(obs) //准备一个vm实例对象let vm = {}vm._data = data = obs//下面的方法只能解析一层解构,多层数据结构需要用到递归function Observer(obj){//汇总对象中所有的属性形成一个数组const keys = Object.keys(obj)//遍历keys.forEach((k)=>{Object.defineProperty(this,k,{get(){return obj[k]},set(val){console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了`)obj[k] = val}})})}
- 劫持多层数据结构的数据
observer(data)function observer(target) {if (typeof target !== 'object' || !target) {return target}for (const key in target) {if (target.hasOwnProperty(key)) {const value = target[key]observerObject(target, key, value)}}
}function observerObject(target, name, value) {if (typeof value === 'object' || Array.isArray(target)) {observer(value);}Object.defineProperty(target, name, {get() {return value},set(newVal) {if (newVal !== value) {if (typeof value === 'object' || Array.isArray(value)) {observer(value)}value = newVal}renderView() //模拟视图渲染操作}})
}