vue作为前端使用广泛的三大框架(react、vue、Angular)之一,vue3的源码已经发布,让我们认识下vue3如何使用proxy做双向数据绑定的。
1、proxy代理概述
proxy是ES6新增对象,用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等); proxy在目标对象的外层搭建一层拦截,外界对目标对象的某些操作,必须通过这层拦截。
var p=new Proxy(target, handler); // target 目标对象 (可以是任何类型的对象,包括原生数组,函数,甚至另一个代理) // handler 一个对象 其属性是(当执行一个操作时定义代理的行为的函数)。
new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为
proxy可以直接代理对象并且返回一个新对象,而不像Object.defineProperty()劫持对象的属性,需要遍历 对象的每个属性,如新增属性时,需要重新遍历对象,对其新增属性再使用Object.defineProperty进行劫持。
const obj={name:'peak'}; const p = new Proxy(obj, { get:(target, key, receiver)=>{ console.log(`getting ${key}!`); return Reflect.get(target, key, receiver); }, set:(target, key, value, receiver)=>{ console.log(target, key, value, receiver); return Reflect.set(target, key, value, receiver); } }); p.name //'peak' 'getting name' 触发get方法 p.age=18 //触发set方法
Proxy支持13种拦截操作
-
get(target, propKey, receiver) 拦截对象属性的读取 比如p.age,p[age];
-
set(target, propKey, receiver) 拦截对象属性的设置 比如 p.age=18,返回一个布尔值
-
has(target, propKey) 拦截 propKey in proxy 的操作,返回一个布尔值。
-
deleteProperty(target, propKey) 拦截删除属性 delete proxy[foo] 和 delete proxy.foo 以及Reflect.deleteProperty() 返回一个布尔值 更多拦截操作说明
2、Reflect
Reflect是内置对象,为操作对象而提供的新API,将Object对象的属于语言内部的方法放到Reflect对象上,即从Reflect对象上拿Object对象内部方法。 将用 老Object方法 报错的情况,改为返回false
//老写法 try { Object.defineProperty(target, property, attributes); // success } catch (e) { // failure } 'name' in Object //true //新写法 if (Reflect.defineProperty(target, property, attributes)) { // success } else { // failure } Reflect.has(Object,'name') //true
Reflect与Proxy是相辅相成的,在Proxy上有的方法,在Reflect就一定有