上篇写Object.defineProperty在vue中的应用后,发现vue3.0已经不用这个了,改用Proxy。官方介绍为:Proxy对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。实际上就是Proxy在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作,必须通过这层拦截。
下面重写一下vue里面的数据代理:
原本我们通过,Object.keys循环,之后通过Object.defineProperty给当前属性,定一个循环传进来的值,每一个值加一个get和set方法,从而实现数据代理。
而使用Proxy我们只需要在superVue函数中写入:
let proxy = new Proxy(me, {
get: function proxyGetter(me,key) {
return me._data[key];
},
set: function proxySetter(me,key,newVal) {
me._data[key] = newVal;
}
});
return proxy;
第一个参数为拦截的目标对象,第二个参数为指定的行为,同样get的时候返回当前代理对象下的name等值,set的时候更新值。打印一下。
let vm = new superVue({
el: "#mvvm-app",
data: {
name: "zhang",
target: "ceshi"
}
})
vm.name = 'zhangsan';
console.log(vm.name);
执行正确。
superVue其他部分就不重写了,简单实现一个双向绑定的例子吧!
html部分
<div id="app">
<h3 id="textcontent"></h3>
<input type="text" id="input"/>
</div>
部分
//获取段落的节点
const textcontent = document.getElementById('textcontent');
//获取输入框节点
const input = document.getElementById('input');
//需要代理的数据对象
const data = {
text: 'hello world'
}
const handler = {
//监控 data 中的 text 属性变化
set: function (target, prop, value) {
if ( prop === 'text' ) {
//更新值
target[prop] = value;
//更新视图
textcontent.innerHTML = value;
input.value = value;
return true;
} else {
return false;
}
}
}
//构造 proxy 对象
const myText = new Proxy(data,handler);
//添加input监听事件
input.addEventListener('input', function (e) {
myText.text = e.target.value; //更新 myText 的值
}, false)
忽略获取dom部分,真实vue中,我们便可以随处给this.text赋值了。