从零开始学习Vue源码 ——响应式基本原理
这里实现一个简易版本的响应式系统来形象的理解数据是如何在初始化的时候被劫持,以及如何在修改时更新视图的。
首先看下Vue2.x实现响应式系统最重要的方法
Object.defineProperty, Vue2.x就是基于它实现的响应式
Object
.defineProperty(obj
, prop
, descriptor
)
具体的属性以及使用方法可以参考MDN
下面贴一个简易版响应式的代码实现
function cb (val
) {
console
.log("视图更新啦~");
}
function defineReactive (obj
, key
, val
) {
Object
.defineProperty(obj
, key
, {
enumerable
: true,
configurable
: true,
get: function reactiveGetter () {
return val
;
},
set: function reactiveSetter (newVal
) {
if (newVal
=== val
) return;
cb(newVal
);
}
});
}
function observer (value
) {
if (!value
|| (typeof value
!== 'object')) {
return;
}
Object
.keys(value
).forEach((key
) => {
if(typeof value
[key
] === 'object') {
observer(value
[key
])
}
defineReactive(value
, key
, value
[key
]);
});
}
class Vue {
constructor(options
) {
this._data
= option
.data
observer(this._data
);
}
}
const vm
= new Vue({
data
: {
name
: {firstName
: 'z', lastName
: 'zz'}
}
})
vm
._data
.name
.firstName
= 'cc'
下面我们一步步解析以上简易版响应式系统原理
首先我们要实现一个对对象属性进行数据劫持,跟踪属性更新的函数 defineReactive , 该函数使用了 Object.defineProperty 进行数据劫持, 被设置的属性会在读取时触发 getter, 会在设置时触发 setter 执行里面更新视图的函数 cb 打印出 视图更新啦~
只有一个defineReactive还不够, 我们还需要实现一个 observer 来对对象所有属性遍历、递归进行绑定, 这样对象上所有属性修改时都会触发getter 、 setter。
最后我们构建一个Vue 的class类, 在构造函数中初始化data,并进行**[响应式]** 化
当实例化Vue后,我们修改_data上的值就会触发setter 更新视图
总结
响应式系统最重要的就是数据劫持部分,当然这里只是一个简单的实现,像数组对象等都没处理,不过能通过这个demo了解相应式的基本原理。