引言
大家都知道Vue双向数据绑定就是指v-model指令,而v-model的本质就是input、value
的语法糖,语法糖就是方便我们代码编写,那么它底层又是怎样实现的呢?本篇将会以不同的vue版本为切入点,进行模拟实现。
vue2.0-Object.definedProperty()
<input type="text" id='inp'>
<div id='view'></div>
<script>
const input = document.getElementById('inp');
const view = document.getElementById('view');
let data = {
// name: 'view'
valueObj:{
name:'view'
}
}
function update() { //更新视图
view.innerText = data.valueObj.name;
}
input.oninput = function () { //更新数据
data.valueObj.name = this.value
}
function observerData(obj) {
if (!obj || typeof obj != 'object') return obj; //容错 + 递归出口
Object.keys(obj).forEach(key => {
definedRective(obj, key, obj[key]);
})
}
observerData(data);
function definedRective(obj, key, val) {
observerData(val); //深层数据递归处理
Object.defineProperty(obj, key, {
get() {
return val;
},
set(newVal) {
if (val === newVal) return; //优化性能
val = newVal;
update();
}
})
}
</script>
缺点
-
不能直接监控数组,而是间接重写Array.prototype上的数组方法(就是vue中常常听见的数组变异方法)比如push、unshfit…属性,监听数组原型上的这些方法,进而实现更新
-
如果被监听对象在执行监听之后又重新添加了属性,这些属性值则无法监听到
vue3.0-Proxy&Reflect
let oProxy = new Proxy(data, {
get(target, key, receiver) {
console.log(1)
return Reflect.get(target, key);
},
set(target, key, newValue, receiver) {
console.log(1)
return Reflect.set(target, key, newValue)
}
});
说明
ES6的Proxy&Reflect
完美解决了ES5Object.definedProperty()
缺点,上面已经指出,但是浏览器不能直接兼容,只能间接通过babel语言降级,因此这里只给出关键代码大家了解一下即可。