web前端高级VUE - vue2.0与vue3.0双向数据绑定的实现原理及区别
vue2.0实现双向数据绑定原理vue2.0中通过利用Object.defineProperty方法监听属性的get和set方法来实现对数据的双向绑定,看如下示例:<!DOCTYPE html><html><head><style></style></head><body>Name: <span id="tx
·
vue2.0实现双向数据绑定原理
vue2.0中通过利用Object.defineProperty方法监听属性的get和set方法来实现对数据的双向绑定,看如下示例:
<!DOCTYPE html>
<html>
<head>
<style>
</style>
</head>
<body>
Name: <span id="txtName"></span>
<br />
<input id='inpName' type="text">
<script>
let obj = {name: ''};
let newObj = JSON.parse(JSON.stringify(obj));
Object.defineProperty(obj, 'name', {
get: function(){
return newObj.name;
}
set: function(val){
if(val === obj.name) return;
newObj.name = val;
observer();
}
});
function observer(){
txtName.innerHTML = obj.name;
inpName.value = obj.name;
}
inpName.oninput = function(){
obj.name = this.value;
}
setTimeout(() => {
obj.name = 'Hello world';
}, 2000);
</script>
</body>
</html>
上面代码中利用Object.defineProperty方法去监听obj对象的name属性的get和set方法。这里需要注意的是:需要对obj对象进行克隆,而在监听函数中的赋值取值操作均操作的是克隆后的对象newObj(避免死循环),因为如果操作原对象obj,这样在get方法中会读取name属性,而只要涉及到读取name属性就会被defineProperty函数监听,这样就造成了死循环。
当对obj的name属性设置值时,会触发set方法,将新值赋值给newObj的name属性同时将新值绑定到视图上,实现属性变视图变。另外需要绑定视图控件的oninput事件,当文本框中的内容发生变化时将新值赋值给obj的name属性同时又会触发监听函数,从而实现了数据的双向绑定。
vue3.0实现双向数据绑定原理
<!DOCTYPE html>
<html>
<head>
<style>
</style>
</head>
<body>
Name: <span id="txtName"></span>
<br />
<input id='inpName' type="text">
<script>
let obj = {name: ''};
obj = new Proxy(obj, {
get(target, prop){
return target[prop];
}
set(target, prop, value){
target[prop] = value;
observer();
}
});
function observer(){
txtName.innerHTML = obj.name;
inpName.value = obj.name;
}
inpName.oninput = function(){
obj.name = this.value;
}
setTimeout(() => {
obj.name = 'Hello world';
}, 2000);
</script>
</body>
</html>
3.0中的绑定原理与2.0中的原理基本一致都是通过监听属性值来改变视图值,然后通过视图的input事件而改变属性值。不同都是这里使用了ES6中的新语法Proxy来实现数据监听。
二者的区别
- 2.0中使用的是Object.defineProperty实现对属性的监听。缺点是一定要克隆一个新的对象进行操作,否则就会造成死循环。第二个缺点是如果有多个属性,那么就要定义多个Object.defineProperty去分别监听每一个属性。
- 3.0中使用了ES6中的新语法,用到了Proxy去实现监听,这样省去了克隆对象的步骤,同时不管有多少个属性只需要定义一次Proxy就可以实现多对象的监听,不同分别定义。
更多推荐
已为社区贡献3条内容
所有评论(0)