响应式系统的基本原理
Vue基于
Object.defineProperty
来实现响应式,对于Object.defineProperty
大家就算不熟悉也听说过,我之前的文章也详细介绍过。
语法大家参考文档即可。
在上次的Vue原理学习(一)中,我们画了一张图,其中有一个_init
的过程,也就是new Vue
之后。
而_init
的过程,会对数据进行响应式的处理。
我们先来看看代码:
function defineDispose(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true, // 可枚举
configurable: true, // 可配置、可重写
get: function() {
return val; // 返回value,在这里Vue会产生依赖收集
},
set: function(newVal) {
if(newVal === val) return
cb(newVal)
}
})
}
这里我们用一个函数对Object.property
进行了简单的封装,并且在set
的时候,调用了一个cb
函数。
// cb函数
function cb (newVal) {
console.log('数据发生了更新: ' + newVal);
}
到这里,虽然代码可以正常工作,但是依然是不够的,我们需要在封装一层observer
。传入一个value
,也就是需要响应式的对象,在通俗点说,就是new Vue()
的时候, 传入的那个参数对象。
function observer(value) {
Object.keys(value).forEach(key => {
// 调用defineDispose函数
defineDispose(value, key, value[key]);
})
}
这里,我们使用遍历来对每个对象属性进行了Object.defineProperty
处理,也就是响应式处理,当然,这个实际的过程会复杂很多,比如需要对数据类型判断、算法处理等等。
最后,我们实现可以通过new Vue
的方式来初始化对象:
class Vue{
// 构造函数
constructor(options) {
this._data = options.data; // 只对data处理
observer(this._data); // 调用observer
}
}
最后我们来调用一下:
let vue = new Vue({
data: {
title: '中国第一艘国产航母13日清晨离开码头 开始海试'
}
});
// 更新数据
vue._data.title = '中超-恒大2-2华夏近4场不胜 鲁能压哨平权健';
// 此时会调用cb函数打印如下数据:
// 数据发生了更新: 中超-恒大2-2华夏近4场不胜 鲁能压哨平权健
这里,我们对Vue的响应式有了一个基本的认识,整个过程也为我们复习了Object.defineProperty
。当然,实际的过程会比这复杂的多。
在刚才的代码中,我们发现,必须使用_data
的改变才可以,但是Vue中却可以直接使用this.xxx
,实际上Vue本质也是 _data
,只不过是使用了数据代理,将_data
代理到了data
上。
嗯嗯嗯嗯嗯。
以上笔记是我 阅读 掘金小册 所得。
链接:https://juejin.im/book/5a36661851882538e2259c0f?inviteCode=596197525188257fd215e23e
网友评论