vue
Version:
Reactive, component-oriented view layer for modern web interfaces.
89 lines (77 loc) • 1.94 kB
text/typescript
import { remove } from '../util/index'
import config from '../config'
import { DebuggerOptions, DebuggerEventExtraInfo } from 'v3'
let uid = 0
/**
* @internal
*/
export interface DepTarget extends DebuggerOptions {
id: number
addDep(dep: Dep): void
update(): void
}
/**
* A dep is an observable that can have multiple
* directives subscribing to it.
* @internal
*/
export default class Dep {
static target?: DepTarget | null
id: number
subs: Array<DepTarget>
constructor() {
this.id = uid++
this.subs = []
}
addSub(sub: DepTarget) {
this.subs.push(sub)
}
removeSub(sub: DepTarget) {
remove(this.subs, sub)
}
depend(info?: DebuggerEventExtraInfo) {
if (Dep.target) {
Dep.target.addDep(this)
if (__DEV__ && info && Dep.target.onTrack) {
Dep.target.onTrack({
effect: Dep.target,
...info
})
}
}
}
notify(info?: DebuggerEventExtraInfo) {
// stabilize the subscriber list first
const subs = this.subs.slice()
if (__DEV__ && !config.async) {
// subs aren't sorted in scheduler if not running async
// we need to sort them now to make sure they fire in correct
// order
subs.sort((a, b) => a.id - b.id)
}
for (let i = 0, l = subs.length; i < l; i++) {
if (__DEV__ && info) {
const sub = subs[i]
sub.onTrigger &&
sub.onTrigger({
effect: subs[i],
...info
})
}
subs[i].update()
}
}
}
// The current target watcher being evaluated.
// This is globally unique because only one watcher
// can be evaluated at a time.
Dep.target = null
const targetStack: Array<DepTarget | null | undefined> = []
export function pushTarget(target?: DepTarget | null) {
targetStack.push(target)
Dep.target = target
}
export function popTarget() {
targetStack.pop()
Dep.target = targetStack[targetStack.length - 1]
}