vue2的响应式:
核心:
对象:通过defineProperty对对象的已有属性值的读取和修改进行劫持监视/拦截
数组:通过重写数组更新数组的一系列更新元素的方法来实现元素修改的劫持
Object.defineProperty(data, 'count',{
get(){},
set(){}
})
问题:
对象直接新添加的属性或删除已有属性,界面不会自动更新
直接通过下标替换元素或更新length,界面不会自动更新arr[1]={}
vue3的响应式
核心:
通过Proxy(代理):拦截对data任意属性的任意(13种)操作,包括属性值的读写,属性的添加,属性的删除等...
通过 Reflect(反射):动态对被代理对象的相应属性进行特定的操作
Proxy意思就是代理,它的作用是对对象进行拦截,以及数据读取、修改的过滤保护
//假设一个数据对象data,内容为:
var data = {
username: 'Frank',
age: 26
}
现在我们给data创建一个代理proxy
var proxy = new Proxy(data, {set: function(){...}, get: function(){...} })
那么,如果我们需要修改数据,比如正常时:data.username='frank'
有了代理之后是这样:proxy.username='frank'
简单来说,proxy拥有data的属性和权限。
我们在使用Proxy时我们需要用new调用,例如
const p = new Proxy(target, handler)
参数target:是Proxy要包装的目标对象,可以是任意类型的对象,包括原生数组,函数,甚至是另一个代理
参数handler:是一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理p的行为(通俗的说它就是一个处理器,用来监视数据的变化)。它重点的监视方法主要是:handler.get()读取属性值,handler.set()更新属性值,handler.deleteProperty()删除属性值
Reflect是一个内置的对象,它提供拦截JavaScript操作的方法。这些方法与proxy handlers的方法相同。Reflect不是一个函数对象,因此它是不可构造的,不能通过new来调用也不能将它作为一个函数来调用。Reflect的所有属性和方法都是静态的。(通俗的说就是通过反射对象可以把当前的代理对象/目标对象的属性的属性值给反射回去)
new Proxy(date, {
//拦截获取属性值---》读取数据
get(target, prop){
return Reflect.get(target, prop)
},
//拦截设置属性值或添加属性值-----》写入数据
set(target, prop, value){
return Reflect.set(target, prop, value)
}
//拦截删除属性
deleteProperty(target, prop){
return Reflect.deleteProperty(target, prop)
}
})
proxy
文档:
Proxy: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Reflect: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect