Vue.js 的响应式原理是通过 Object.defineProperty() 劫持对象的属性,当这些属性改变时触发视图更新。
实现响应式的步骤:
- 在初始化数据时,遍历 data 对象的属性,使用 Object.defineProperty() 将其转换为 getter/setter。
js
function defineReactive(data, key, val) {
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
console.log('获取值:' + val)
return val
},
set: function reactiveSetter(newVal) {
console.log('设置值:' + newVal)
val = newVal
}
})
}
- 在 getter 中记录依赖,在 setter 中触发依赖更新。
js
let dep = [] // 依赖集合
function defineReactive(data, key, val) {
let dep = new Dep() // 依赖实例
Object.defineProperty(data, key, {
// ...
get: function reactiveGetter() {
// 收集依赖
dep.depend()
return val
},
set: function reactiveSetter(newVal) {
if (val === newVal) return
val = newVal
// 触发依赖更新
dep.notify()
}
})
}
- 编译模板时,遍历解析指令等,并将依赖推送给相应属性的 dep 实例。
js
function compile(node) {
let text = node.textContent
let reg = /\{\{(.*?)\}\}/g
if (reg.test(text)) {
let key = RegExp.$1.trim()
node.textContent = text.replace(reg, val[key])
// 收集依赖
dep.depend()
}
}
- 当依赖的属性变化时,会触发依赖实例的 notify,从而更新视图。
以上就是 Vue.js 响应式系统的底层原理,通过 Object.defineProperty() 将 data 转换为 getter/setter,并依靠依赖收集与触发实现视图的更新。这是 Vue.js 高效响应的基石。