数据响应式是vue的核心原理。
实现原理
借助Object.defineProperty(),利用proxy的设计模式实现。
我们通过Object.defineProperty为对象obj添加属性,可以设置对象属性的getter和setter方法。之后我们每次通过点语法获取属性都会执行这里的getter函数,在这个函数中我们会把调用此属性的依赖收集到一个集合中 ;而在我们给属性赋值(修改属性)时,会触发这里定义的setter函数,在次函数中会去通知集合中的依赖更新,做到数据变更驱动视图变更。
实现原理的demo:
let myData = {n=0}
let data = proxy({data:myData})
function proxy({data}) { //解构赋值
let value = data.n
Object.defineProperty(data, 'n', {
get() {
return value
}
set(newValue) {
value = newValue
}
})
const obj = {}
Object.defineProperty(obj, 'n', {
get() {
return data.n
},
set() {
data.n = value
}
})
}
这个原理导致它又一些bug:当出现未被定义的key时,无法进行响应式。
一般解决办法
- 先声明,再使用
- 使用
Vue.set或this.$set来修改(使用后,该key就有了响应式功能)
数组的mutation method
数组的操作如push等无法用以上两个方法解决,于是Vue篡改了数组的7个API,解决了响应问题。