Vue现在使用非常广泛,那么关于Vue双向绑定是怎么实现的呢
一、Vue2.0实现原理
1.实现原理
Vue2.0是使用Object.defineProperty()
方法来实现的,
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
Object.defineProperty()
有三个参数
Object.defineProperty(obj, prop, descriptor)
obj
要定义属性的对象。
prop
要定义或修改的属性的名称或 Symbol 。
descriptor
要定义或修改的属性描述符。
然后通过get()和set()方法进行数据劫持实现双向绑定
get
属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
默认为 undefined。
set
属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
默认为 undefined。
2.使用Object.defineProperty()做一个简单的功能实现
HTML代码:
姓名:<span id="spanName"></span>
<br>
<input type="text" id="inpName">
JS代码:
let obj = {
name: ''
};
// 深克隆obj
let newObj = JSON.parse(JSON.stringify(obj));
Object.defineProperty(obj, 'name', {
// 这里相当于给数据设置set get
get() {
return newObj.name
},
set(val) {
if (val === obj.name) return;
newObj.name = val;
observer()
}
})
function observer() {
spanName.innerHTML = obj.name
inpName.value = obj.name
}
observer();
setTimeout(() => {
obj.name = inpName.value
}, 1000)
// 这里在vue相当于v-model
inpName.oninput = function () {
obj.name = this.value
}
二、Vue3.0实现原理
1.实现原理
Vue3.0是使用Proxy来实现的,
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
Proxy
有两个参数
const p = new Proxy(target, handler)
target
要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
2.使用Proxy()做一个简单的功能实现
HTML代码:
姓名:<span id="spanName"></span>
<br>
<input type="text" id="inpName">
JS代码:
let obj = {}
// 直接把整体属性监听了
obj = new Proxy(obj, {
get(target, prop) {
return target[prop];
},
set(target, prop, value) {
target[prop] = value;
observer()
}
})
function observer() {
spanName.innerHTML = obj.name
inpName.value = obj.name
}
observer();
setTimeout(() => {
obj.name = '1'
}, 1000)
// 这里在vue相当于v-model
inpName.oninput = function () {
obj.name = this.value
}
# 总结
Vue2.0是使用Object.defineProperty()
进行数据劫持实现双向绑定的。
Vue3.0是使用Proxy()
Vue3.0实现双向绑定比Vue2.0实现双向绑定有两个优点
- 不需要把原始数据进行克隆
- 不需要分别给对象中的每一个属性设置监听