Computed und Watch werden in Interviews oft nach ihren Unterschieden gefragt, also schauen wir uns ihre spezifische Implementierung anhand der Quellcode-Implementierung an
// packages/reactivity/src/computed.ts export function computed<T>( getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>, debugOptions?: DebuggerOptions, isSSR = false ) { let getter: ComputedGetter<T> let setter: ComputedSetter<T> const onlyGetter = isFunction(getterOrOptions) if (onlyGetter) { getter = getterOrOptions setter = __DEV__ ? () => { console.warn('Write operation failed: computed value is readonly') } : NOOP } else { getter = getterOrOptions.get setter = getterOrOptions.set } // new ComputedRefImpl const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR) if (__DEV__ && debugOptions && !isSSR) { cRef.effect.onTrack = debugOptions.onTrack cRef.effect.onTrigger = debugOptions.onTrigger } // 返回ComputedRefImpl实例 return cRef as any }
Sie können sehen, dass Computed intern zuerst nur Getter und Setter verarbeitet. und dann wird ein neues ComputedRefImpl zurückgegeben. Wenn Sie die Implementierung der Ref-API kennen, können Sie feststellen, dass ihre Implementierungen viele Ähnlichkeiten aufweisen von ref (für diejenigen, die mit der ref-Implementierung nicht vertraut sind, lesen Sie bitte das vorherige Kapitel), der einzige Unterschied besteht in der Beurteilung des _dirty-Werts. Dies ist, was wir oft sagen, dass der berechnete Wert den Wert zwischenspeichert Wert muss aktualisiert werden?
Zusammenfassung:
So computed verfügt über zwei Ebenen der reaktionsfähigen Verarbeitung. Eine Ebene ist die Beziehung zwischen berechnetem Wert und der Wirkung der Funktion (ähnlich der Implementierung von ref), und die andere Ebene ist der berechnete Getter und die reaktionsfähigen Daten . Beziehung.
// packages/reactivity/src/computed.ts export class ComputedRefImpl<T> { public dep?: Dep = undefined // 存储effect的集合 private _value!: T public readonly effect: ReactiveEffect<T> public readonly __v_isRef = true public readonly [ReactiveFlags.IS_READONLY]: boolean = false public _dirty = true // 是否需要重新更新value public _cacheable: boolean constructor( getter: ComputedGetter<T>, private readonly _setter: ComputedSetter<T>, isReadonly: boolean, isSSR: boolean ) { // 创建effect this.effect = new ReactiveEffect(getter, () => { // 调度器执行 重新赋值_dirty为true if (!this._dirty) { this._dirty = true // 触发effect triggerRefValue(this) } }) // 用于区分effect是否是computed this.effect.computed = this this.effect.active = this._cacheable = !isSSR this[ReactiveFlags.IS_READONLY] = isReadonly } get value() { // the computed ref may get wrapped by other proxies e.g. readonly() #3376 // computed ref可能被其他代理包装,例如readonly() #3376 // 通过toRaw()获取原始值 const self = toRaw(this) // 收集effect trackRefValue(self) // 如果是脏的,重新执行effect.run(),并且将_dirty设置为false if (self._dirty || !self._cacheable) { self._dirty = false // run()方法会执行getter方法 值会被缓存到self._value self._value = self.effect.run()! } return self._value } set value(newValue: T) { this._setter(newValue) } }
watch
watch ist einfacher als berechnet, da nur Getter und eingerichtet werden müssen Reaktionsfähigkeit Die Beziehung zwischen Daten besteht darin, den vom Benutzer übergebenen Rückruf aufzurufen, wenn sich die Reaktionsdaten ändern, und den alten und neuen Wert zu übergeben
// packages/reactivity/src/effect.ts export function triggerEffects( dep: Dep | ReactiveEffect[], debuggerEventExtraInfo?: DebuggerEventExtraInfo ) { // spread into array for stabilization const effects = isArray(dep) ? dep : [...dep] // computed的effect会先执行 // 防止render获取computed值得时候_dirty还没有置为true for (const effect of effects) { if (effect.computed) { triggerEffect(effect, debuggerEventExtraInfo) } } for (const effect of effects) { if (!effect.computed) { triggerEffect(effect, debuggerEventExtraInfo) } } }
// packages/runtime-core/src/apiWatch.ts export function watch<T = any, Immediate extends Readonly<boolean> = false>( source: T | WatchSource<T>, cb: any, options?: WatchOptions<Immediate> ): WatchStopHandle { if (__DEV__ && !isFunction(cb)) { warn(...) } // watch 具体实现 return doWatch(source as any, cb, options) }
Das obige ist der detaillierte Inhalt vonVue3 berechnet und analysiert den Quellcode. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!