模拟vue数据劫持实现发布订阅核心代码
// 定义一个依赖收集器
class Dep {
constructor() {
this.subs = [] // 订阅者列表
}
// 添加订阅者
addSub(sub) {
this.subs.push(sub)
}
// 通知所有订阅者数据已更新
notify() {
this.subs.forEach(sub => sub.update())
}
}
// 定义一个观察者
class Watcher {
constructor(vm, exp, cb) {
this.vm = vm
this.exp = exp
this.cb = cb
this.value = this.get() // 初始化值
}
// 获取当前值
get() {
Dep.target = this // 将当前订阅者指向该自身
let value = this.vm[this.exp] // 获取当前值,并触发依赖收集
Dep.target = null // 收集完毕后,将订阅者置空
return value
}
// 当被依赖的数据更新时,触发更新回调
update() {
let value = this.vm[this.exp]
if (value !== this.value) {
this.cb.call(this.vm, value, this.value)
this.value = value
}
}
}
// 数据劫持函数
function observe(obj, vm) {
if (!obj || typeof obj !== 'object') {
return
}
Object.keys(obj).forEach(key => {
defineReactive(vm, key, obj[key])
})
}
// 定义一个数据劫持函数
function defineReactive(vm, key, val) {
let dep = new Dep() // 定义依赖收集器
Object.defineProperty(vm, key, {
get() {
if (Dep.target) {
dep.addSub(Dep.target) // 添加订阅者
}
return val
},
set(newVal) {
if (newVal === val) {
return
}
val = newVal
dep.notify() // 数据更新,通知所有订阅者
}
})
}
以上代码中,Dep类是依赖收集器,Watcher类是观察者,defineReactive函数是数据劫持函数。在数据劫持过程中,会监听对象的属性的变化,一旦有变化会触发数据改变的通知,通知所有已经订阅当前值的订阅者进行数据更新。同时,也提供了添加订阅者和通知订阅者更新的接口。
以上就是模拟vue数据劫持实现发布订阅核心代码全部内容,感谢大家支持自学php网。



