源码位置: https://github.com/vuejs/vue-next/blob/master/packages/reactivity/src/computed.ts
computed
接收一个参数可以是一个 function
或者是一个对象,对象必须有 get
方法,可以设置 set
方法,返回一个有 value
属性的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
export function computed<T>( getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T> ) { let getter: ComputedGetter<T> let setter: ComputedSetter<T> if (isFunction(getterOrOptions)) { getter = getterOrOptions setter = __DEV__ ? () => { console.warn('Write operation failed: computed value is readonly') } : NOOP } else { getter = getterOrOptions.get setter = getterOrOptions.set }
return new ComputedRefImpl( getter, setter, isFunction(getterOrOptions) || !getterOrOptions.set ) as any }
|
ComputedRefImpl 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
class ComputedRefImpl<T> { private _value!: T private _dirty = true
public readonly effect: ReactiveEffect<T> public readonly __v_isRef = true; public readonly [ReactiveFlags.IS_READONLY]: boolean
constructor( getter: ComputedGetter<T>, private readonly _setter: ComputedSetter<T>, isReadonly: boolean ) { this.effect = effect(getter, { lazy: true, scheduler: () => { if (!this._dirty) { this._dirty = true trigger(toRaw(this), TriggerOpTypes.SET, 'value') } } })
this[ReactiveFlags.IS_READONLY] = isReadonly }
get value() { if (this._dirty) { this._value = this.effect() this._dirty = false } track(toRaw(this), TrackOpTypes.GET, 'value') return this._value }
set value(newValue: T) { this._setter(newValue) } }
|
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| setup() { const a = Vue.ref(1) const b = Vue.computed(() => { console.log("computed"); return a.value * 2 }) a.value = 2; a.value = 3; a.value = 4; console.log(b.value) a.value = 5; a.value = 6; console.log(b.value) console.log(Vue.isRef(b)) }
|