双向数据绑定
前言
双向数据绑定指的是view层和model层数据同步,当视图层数据发生改变的时候,模型层也会改变,反之亦然。
一、vue2中的原理
通过数据劫持结合发布者订阅者模式实现
核心:Object.defineProperty()方法
通过defineProperty对对象的已有属性值的读取和修改进行劫持(监视/拦截)
//核心方法 -
Object.defineProperty(obj, prop, descriptor)
// obj:要在其上定义属性的对象。
// prop:要定义或修改的属性的名称。
// descriptor:将被定义或修改的属性描述符。
Object.defineProperty(对象, 属性, {
get () {},
set () {}
})
<body>
<div id="app">
<input id="input" type="text">
<span id="content"></span>
</div>
</body>
<script type="text/javascript">
let data = {
}
Object.defineProperty(data, 'text', {
set: function (v) {
this.value = v
//当我们为data.text赋值时,实际上更改的是this.value,
//这里的this.value是我们添加的一个变量,用于保存data.text的内容,
//也可以是任意的其他变量,比如this.a = v,效果也是一样的。
console.log('set', this.value)
document.getElementById('content').innerText = this.value
},
get: function () {
console.log('get', this.value)
return this.value //当我们获取data.text时,其实也是获取到this.value的值
}
})
data.age = 99
data.text = 99
console.log(data.text);
document.getElementById('input').addEventListener('input', function (e) {
console.log(e);
data.text = e.target.value
})
</script>
二、vue3中的原理
通过Proxy(代理)的方式实现 拦截对data任意属性的操作, 包括属性值的读写, 属性的添加, 属性的删除等...
通过 Reflect(反射): 动态对被代理对象的相应属性进行特定的操作
代码如下(示例):
<script>
const user = {
name: "John",
age: 12
};
/*
proxyUser是代理对象, user是被代理对象
后面所有的操作都是通过代理对象来操作被代理对象内部属性
*/
const proxyUser = new Proxy(user, {
get(target, prop) {
console.log(prop)
return Reflect.get(target, prop)
},
set(target, prop, val) {
console.log(prop, val)
return Reflect.set(target, prop, val); // (2)
},
deleteProperty (target, prop) {
console.log(prop)
return Reflect.deleteProperty(target, prop)
}
});
// 读取属性值
console.log(proxyUser===user)
console.log(proxyUser.name, proxyUser.age)
// 设置属性值
proxyUser.name = 'bob'
proxyUser.age = 13
console.log(user)
// 添加属性
proxyUser.sex = '男'
console.log(user)
// 删除属性
delete proxyUser.sex
console.log(user)
</script>