用过Vue的小伙伴,都知道,Vue中有个v-model的属性,可以把表单元素与某个属性绑定起来。
它的实现原理:vue 2.0版本用到了Object.dfineProperty()方法;而vue 3.0版本是利用了ES6语法中的proxy。下面,我们来探讨一下两者的用法,这样,会帮助我们更好的理解Vue的数据与视图之间的关联。
<span id="spanVal"></span>
<br />
<input type="text" value="" id="iptValue">
let obj = {
data:''
}
// 防止在obj对象中调用get()方法时,进入死循环
let newObj = JSON.parse(JSON.stringfy(obj));
// 利用Object中的方法
Object.defineProperty(obj,'data',{
get(){
return newObj.name;
},
set(val){
newObj.name = val;
changeDate();
}
}
)
// 封装数据改变后,绑定的方法
function changeDate(){
spanVal.innerHTML = obj.name;
iptValue.value = obj.name;
}
// 监听输入框输入的值的同时,亦调用了Object.defineProperty()
iptValue.oninput = function () {
obj.name = this.value;
}
以上就是通过Object.defineProperty(),来设置数据的双向绑定,这也是Vue 2.0版本,v-model用到的原理。
下面是ES6中,使用proxy拦截,实现数据的双向绑定:
let obj = {};
obj = new Proxy(obj, {
// target在这也就是obj, prop的值表示了obj中的属性名
get(target, prop) {
return target[prop];
},
// value是用户输入的值(或把输入框输入的值,进行obj对象的更新)
set(target, prop, value) {
target[prop] = value;
observe();
}
});
function observe() {
spanVal.innerHTML = obj.name;
iptValue.value = obj.name;
};
iptValue.oninput = function () {
obj.name = this.value;
}
以上可以看出,proxy拦截器,好像要比Object.defineProperty(),要简单些。当然,在ES6的语法中,proxy的用途远比这要广,这只是其中的一种用法。