响应式系统
Vue.js是一款MVVM框架,数据模型仅仅是普通的JavaScript对象,但是对象的操作能影响视图,其核心就是响应式系统。
Object.defineProperty
使用方法:
/*
obj: 目标对象
prop: 需要操作的目标对象的属性名
descriptor: 描述符
return value 传入对象
*/
Object.defineProperty(obj, prop, descriptor)
descriptor的一些属性
- enumerable 属性是否可以枚举 默认false
- configurable 属性是否可以被修改 默认false
- get 获取属性的方法
- set 设置属性的方法
实现observe(可观察的)
首先我们定义一个简单的view函数,这个函数用来模拟视图更新。
function view(val) {
// TODO 渲染视图
console.log('视图更新了');
}
Vue.js中源代码是通过定义一个defineReactive方法对Object.defineProperty进行封装了。
function defineReactive(data, key, val) {
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function () {
return val;
},
set: function (newVal) {
if (val === newVal){
return;
}
val = newVal;
}
})
}
我们在上面在封装一个observer,它可以对一个对象的所有属性及子属性都转化为可侦测的。此处我们暂时只做第一层的侦测,多层的侦测可以通过在defineReacticve中判断typeof 为 object 时候继续调用observer,具体可以参考 object的变化侦测
function observer(value) {
if (!value || (typeof value !== 'object')) {
return;
}
Object.keys(value).forEach((key) => {
defineReactive(value, key, value[key]);
});
}
在 Vue 的构造函数中,对 options 的 data 进行处理,这里的 data 想必大家很熟悉,就是平时我们在写 Vue 项目时组件中的 data 属性(实际上是一个函数,这里当作一个对象来简单处理)。
class Vue {
/* Vue构造类 */
constructor(options) {
this._data = options.data;
observer(this._data);
}
}
这样我们只要 new 一个 Vue 对象,就会将 data 中的数据进行「响应式」化。如果我们对 data 的属性进行下面的操作,就会触发 cb 方法更新视图。
let o = new Vue({
data: {
test: "I am test."
}
});
o._data.test = "hello,world."; // 视图更新了