day130-vuejs源码-数据绑定-2

前言

这次是再一次看watcher.js中的东西了,一直对dep涉及的闭包有点模糊。希望这次能懂更多点。

代码

// 再看数据绑定中的Watcher,class Watcher
// ...变量定义
get () {
/**
* Dep中的pushTarget
* export function pushTarget (target: ?Watcher) {
targetStack.push(target)
Dep.target = target
}

*/
pushTarget(this)
let value
const vm = this.vm

/*
执行了getter操作,看似执行了渲染操作,其实是执行了依赖收集。
在将Dep.target设置为自身观察者实例以后,执行getter操作。
譬如说现在的的data中可能有a、b、c三个数据,getter渲染需要依赖a跟c,
那么在执行getter的时候就会触发a跟c两个数据的getter函数,
在getter函数中即可判断Dep.target是否存在然后完成依赖收集,
将该观察者对象放入闭包中的Dep的subs中去。
*/
if (this.user) {
try {
value = this.getter.call(vm, vm)
} catch (e) {
handleError(e, vm, `getter for watcher "${this.expression}"`)
}
} else {
value = this.getter.call(vm, vm)
}
// "touch" every property so they are all tracked as
// dependencies for deep watching
if (this.deep) {
/*递归*/
traverse(value)
}

/**
* dep中的popTarget
* export function popTarget () {
targetStack.pop()
Dep.target = targetStack[targetStack.length - 1]
}
*/
popTarget()
this.cleanupDeps()
return value
}

/**
* Add a dependency to this directive().
*/
addDep (dep: Dep) {
const id = dep.id
if (!this.newDepIds.has(id)) {
this.newDepIds.add(id)
this.newDeps.push(dep)
if (!this.depIds.has(id)) {
dep.addSub(this)
}
}
}

/**
* Clean up for dependency collection.
*/
cleanupDeps () {
/*移除所有观察者对象*/
let i = this.deps.length
while (i--) {
const dep = this.deps[i]
if (!this.newDepIds.has(dep.id)) {
dep.removeSub(this)
}
}
let tmp = this.depIds
this.depIds = this.newDepIds
this.newDepIds = tmp
this.newDepIds.clear()
tmp = this.deps
this.deps = this.newDeps
this.newDeps = tmp
this.newDeps.length = 0
}

/**
* Subscriber(注:调度者) interface.
* Will be called when a dependency changes.
*/
/*
调度者接口,当依赖发生改变的时候进行回调。
*/
update () {
/* istanbul ignore else */
if (this.lazy) {
this.dirty = true
} else if (this.sync) {
/*同步则执行run直接渲染视图*/
this.run()
} else {
/*异步推送到观察者队列中,由调度者调用。*/
queueWatcher(this)
}
}

/**
* Scheduler job interface.
* Will be called by the scheduler.
*/
run () {
if (this.active) {
const value = this.get()
if (
value !== this.value ||
// Deep watchers and watchers on Object/Arrays should fire even
// when the value is the same, because the value may
// have mutated.
/*
即便值相同,拥有Deep属性的观察者以及在对象/数组上的观察者应该被触发更新,因为它们的值可能发生改变。
*/
isObject(value) ||
this.deep
) {
// set new value
const oldValue = this.value
/*设置新的值*/
this.value = value

/*触发回调渲染视图*/
if (this.user) {
try {
this.cb.call(this.vm, value, oldValue)
} catch (e) {
handleError(e, this.vm, `callback for watcher "${this.expression}"`)
}
} else {
this.cb.call(this.vm, value, oldValue)
}
}
}
}

/**
* Evaluate the value of the watcher.
* This only gets called for lazy watchers.
*/
/*获取观察者的值*/
evaluate () {
this.value = this.get()
this.dirty = false
}

/**
* Depend on all deps collected by this watcher.
*/
/*收集该watcher的所有deps依赖*/
depend () {
let i = this.deps.length
while (i--) {
this.deps[i].depend()
}
}

/**
* Remove self from all dependencies' subscriber list.
*/
/*将自身从所有依赖收集订阅列表删除*/
teardown () {
if (this.active) {
// remove self from vm's watcher list
// this is a somewhat expensive operation so we skip it
// if the vm is being destroyed.
/*从vm实例的观察者列表中将自身移除,由于该操作比较耗费资源,所以如果vm实例正在被销毁则跳过该步骤。--引*/
if (!this.vm._isBeingDestroyed) {
remove(this.vm._watchers, this)
}
let i = this.deps.length
while (i--) {
this.deps[i].removeSub(this)
}
this.active = false
}
}
文章作者: lmislm
文章链接: http://lmislm.com/2019/05/22/2019-05-22/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LMISLMのBlog