class Observer{ // 响应式处理器
constructor(data){
this.data = data
if(!Array.isArray(data)) this.walk(data)
}
walk(data){
for(let key in data){
defineReactive(data,key,data[key])
}
}
}
function defineReactive(data,key,value) { // 响应式
if(typeof value ==='object') new Observer(value)
let dep = new Dep()
Object.defineProperty(data,key,{
enumerable:true,
configurable:true,
get(){
dep.depend()
return value
},
set(newValue){
if(value===newValue) return
value = newValue
dep.notify()
}
})
}
class Watcher{ // 观察者
constructor(vm,exp,cb){
this.vm = vm
this.getter = parsePath(exp)
this.value = this.get()
this.cb = cb
}
get(){
window.target = this
let value = this.getter.call(this.vm,this.vm)
window.target = undefined
return value
}
update(){
let oldValue = this.value
this.value = this.get()
this.cb&&this.cb.call(this.vm,this.value,oldValue)
}
}
function parsePath(exp) {
if(/[^\w.$]/.test(exp)) return
let segments = exp.split('.')
return (obj)=>{
for(let key of segments){
obj = obj[key]
}
return obj
}
}
class Dep{ // 发布订阅者
constructor(){
this.deps = []
}
depend(){
if(window.target) this.addSub(window.target)
}
addSub(sub){
this.deps.push(sub)
}
notify(){
for(let watcher of this.deps){
watcher.update()
}
}
}
let vm = new Vue({
data(){
return{
list:[...]
}
}
})
new Observer(vm.$data)
new Watcher(vm,$data.list,fn)
1.状态data
经过响应式处理器Observer
设置成getter/setter
2.Watcher
作为状态的观察者,View通过watcher.get()
获取vm内部状态并渲染的同时会将watcher
挂载到window.target
,同时会触发状态的getter
从而通过dep.depend()
将watcher
订阅进依赖列表deps
3.Dep
作为watcher的订阅发布者,在状态getter
时将watcher
订阅进deps,在状态改变setter
时,通过dep.notify()
从deps取出订阅的watcher
并通过watcher.update()
通知其更改观察的状态并重新渲染view