vue 實現個簡易版(4)
阿新 • • 發佈:2020-09-17
上一篇文章實現了v-bind, v-on指令以及methods等,這一篇來實現computed和watch;
1. computed
在Vue例項中通過this可以直接訪問computed中的計算屬性,而且它可以實現快取,並且只有當依賴的資料變化才會更新;
1.1 ComputedWatcher
需要定義一個ComputedWatcher,它跟Watcher基本相同,只是再設定值的時候,需要跟新快取的老值
class ComputedWatcher { constructor(vm, expr, cb) { this.vm = vm this.expr = expr this.cb = cb this.value = this.get() } get() { Dep.target = this let oldValue = CompilerUtil.getVal(this.vm, this.expr) Dep.target = null return oldValue } update() { let newVal = CompilerUtil.getVal(this.vm, this.expr) if (newVal !== this.value) { this.value = newVal // 跟Watcher不同 this.cb(newVal) } } }
1.2 在取data中值是判斷 是否是取computed 中的值
修改CompilerUtil中的取值函式getVal,加入判斷
getVal(vm, expr) {
return expr.split('.').reduce((data, key) => {
if (key in vm.$computed) { // 1.2 新增
return vm.$computed[key].call(vm)
}
return data[key]
}, vm.$data)
}
1.3 在設定值前加入依賴,快取舊值,並在資料更新的時候,更新computed 中的值以及檢視
修改CompilerUtil中的取值函式setTextContent,加入判斷
setTextContent(node, expr, vm) { let content let fn = this.updater['textUpdater'] let k = (/\{\{(.+?)\}\}/g).exec(expr)[1] //1.3 獲取{{ }} if (k in vm.$computed) {//1.3 // new ComputedWatcher的時候快取舊值,加入依賴 let computed = new ComputedWatcher(vm, k, (newVal) => { fn(node, newVal) }) content = computed.value } else { content = expr.replace(/\{\{(.+?)\}\}/g, (...args) => { new Watcher(vm, args[1], (newVal) => { fn(node, newVal) }) return this.getVal(vm, args[1])//school.age }) } fn(node, content) }
至此computed功能基本完成
2. watch
2.1 修改Watcher類的update函式,接收上一次的值oldValue,更新vm.$watch中的函式傳遞newVal和oldValue
update(oldValue) {
let newVal = CompilerUtil.getVal(this.vm, this.expr)
let timer = null
if (newVal !== this.value) {
this.cb(newVal,oldValue)
if (this.expr in this.vm.$watch) {
vm.$watch[this.expr].call(this.vm, newVal, oldValue)
}
}
}
2.2 修改Dep類中的notify函式接收上一次的值oldValue,
notify(oldValue) {
this.subscribers.forEach(watcher => watcher.update(oldValue));
}
2.3 修改Observer類中的defindReactive函式中的Object.defineProperty的set函式
set: (newValue) => {
// 當賦的值和老值一樣,就不重新賦值
if (newValue != value) {
let oldValue = value //2.3 新增
this.observer(newValue)//新值,做成響應式
value = newValue
dep.notify(oldValue) //2.3修改
}
}
到此為止watch的原理,也基本實現了。