首先,我们需要实现一个Dep类,用于管理所有的观察者(Watcher):
class Dep {
constructor () {
this.subs = []
}
addSub (sub) {
this.subs.push(sub)
}
notify () {
this.subs.forEach((sub) => {
sub.update()
})
}
}
然后,我们需要实现一个Observer类,用于给对象的每个属性添加getter和setter,实现数据的响应式:
class Observer {
constructor (value) {
this.walk(value)
}
walk (obj) {
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key])
})
}
}
function defineReactive (obj, key, val) {
const dep = new Dep()
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get () {
Dep.target && dep.addSub(Dep.target)
return val
},
set (newVal) {
if (newVal === val) return
val = newVal
dep.notify()
}
})
}
接下来,我们需要实现一个Watcher类,用于观察数据的变化:
class Watcher {
constructor (vm, key, cb) {
this.vm = vm
this.key = key
this.cb = cb
Dep.target = this
this.vm[this.key]
Dep.target = null
}
update () {
this.cb.call(this.vm, this.vm[this.key])
}
}
最后,我们实现一个简单的Vue类,接受一个options参数,并初始化数据:
class Vue {
constructor (options) {
this.$options = options
this.$data = options.data
new Observer(this.$data)
this.proxyData(this.$data)
}
proxyData (data) {
Object.keys(data).forEach(key => {
Object.defineProperty(this, key, {
enumerable: true,
configurable: true,
get () {
return data[key]
},
set (newVal) {
data[key] = newVal
}
})
})
}
}
这个简单的Vue实现支持以下用法:
let vm = new Vue({
data: {
test: 'I am test.'
}
})
new Watcher(vm, 'test', (value) => {
console.log('watch:', value)
})
setTimeout(() => {
vm.test = 'Hello, world!'
}, 1000)
在这个例子中,我们创建了一个Vue实例,并添加了一个Watcher来观察test
属性。当我们在1秒后更改test
的值时,Watcher将会被通知,并打印出新的值。
这只是Vue的数据响应式系统的一个非常基础和简化的示例,真正的Vue源码包含了更多的功能和优化,例如计算属性,依赖收集优化,异步更新队列,虚拟DOM,模板编译,指令,生命周期钩子等等。如果你想要更深入地理解Vue的工作原理,我建议你直接阅读Vue的源码。