Vue2实现响应式的外围:
- 对象:通过defineProperty对对象的已有属性值的读取和批改进行劫持(监督/拦挡)
- 数组:通过重写数组更新数组一系列更新元素的办法来实现元素批改的劫持
1、应用observe函数遍历data的每个属性
2、调用Object.defineProperty()对每个属性做响应式解决:利用拦截器属性get()和set()办法做订阅-公布解决。
3、当对一个属性进行响应式解决的适宜,会实例化一个Dep实例,并将用到这个属性的组件所对应的Watcher实例全副寄存在subs数组里,当属性被批改时,告诉watcher,调用外面的render函数,进行dom的diff和更新。
问题:
- 须要遍历须要监听的每个对象的每个属性,对其增加definePropert办法,通过其外部的get()和set()办法进行数据的监听和拦挡,实现非常复杂。
- 对象间接新增加的属性或删除已有属性,界面不会自动更新,须要应用Vue.set()
- 间接通过下标替换元素或更新length,界面也不会自动更新
- 数据的响应式解决和视图未齐全解耦
Vue3实现响应式的外围:
通过proxy代理:拦挡对data任意属性的任意操作,包含属性值的读写,属性的增加,属性的删除等。
通过reflect反射,动静对被代理对象的相应属性进行特定的操作。
//申明一个一般对象,让其变成一个proxy代理响应式对象let user = { name: 'Liane', age: 18}//通过new运算符,实例化一个proxy对象,new Proxy(target, handler)//参数1、target--指标对象//参数2、handler--处理器对象,用来监督数据,及数据操作let proxyUser = new Proxy(user, { //获取指标对象的某个属性值 get(target, prop) { console.log('get办法调用了') //通过Reflect反射,对被代理对象(指标对象)的相应属性进行特定操作 return Reflect.get(target, prop) }, //批改指标对象的属性值/为指标对象增加新的属性 set(target, prop, value) { console.log('set办法调用了') return Reflect.set(target, prop, value) }, //删除指标对象上的某个属性值 deleteProperty(target, prop) { console.log('delete办法调用了') return Reflect.deleteProperty(target, prop) }})console.log(proxyUser) //Proxy {name:"Liane",age:18}//通过代理对象获取指标对象中的某个属性值console.log(proxyUser.name) //Liane//批改源对象的属性,代理对象的值也会批改user.name = 'Ann'console.log(proxyUser.name) //Ann//通过代理对象,批改指标对象上的属性值proxyUser.name = 'Rose'console.log(user.name) //Rose//通过代理对象,删除指标对象上的属性值delete proxyUser.nameconsole.log(user) //{age:18}</script >
长处:
- 在咱们动静为data增加属性时,不须要做任何解决,这个属性就曾经是响应式的了。(不必循环遍历data的每个属性,对属性都做一遍响应式解决,而是间接代理整个data对象)
- 数组的任何操作也能够触发相应。