平常在写 Vue 项目时,免不了要写一些 computed 来包装、计算一些数据。以方便我们使用。来看下 Vue3 中 computed 都做了什么。
export function computed<T>(
getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>
) {
//初始化 getter、setter 和 副作用函数
const c = _computed(getterOrOptions as any)
//执行当前实例的副作用函数
recordInstanceBoundEffect(c.effect)
return c
}
代码位置:packages/runtime-core/src/apiComputed.ts
// 第一种:
const doubbleCount = computed(()=>num.value+1)
// 第二种:
const doubbleCount = computed({
get: () => num.value + 1,
set: val => num.value = val + 10
})
export function computed(getterOrOptions) {
//定义 getter 和 setter
let getter
let setter
//先判断是否是函数?
if (isFunction(getterOrOptions)) {
//把我们写的 computed函数 赋值给 getter
getter = getterOrOptions
//如果是开发环境赋值 一个包含错误信息的函数,如果是生产环境,赋值一个空函数
setter = __DEV__
? () => {
console.warn(\\\'Write operation failed: computed value is readonly\\\')}
: NOOP
} else {
//如果我们是以第二种方式传入的参数,那就直接赋值对应的 getter 和 setter
getter = getterOrOptions.get
setter = getterOrOptions.set
}
//返回一个类,收集依赖、派发事件
return new ComputedRefImpl(
getter,
setter,
isFunction(getterOrOptions) || !getterOrOptions.set
)
}
代码文件:packages/reactivity/src/computed.ts
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, {
//true 函数延迟执行
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)
}
}
代码文件:packages/reactivity/src/computed.ts
export function effect<T = any>(
fn: () => T,
options: ReactiveEffectOptions = EMPTY_OBJ
): ReactiveEffect<T> {
//是否是副作用函数
if (isEffect(fn)) {
fn = fn.raw
}
//创建副作用函数
const effect = createReactiveEffect(fn, options)
//是否立即执行
if (!options.lazy) {
effect()
}
return effect
}
recordInstanceBoundEffect(c.effect)
//方法
export function recordInstanceBoundEffect(
effect: ReactiveEffect,
instance = currentInstance
)
{
if (instance) {
;(instance.effects || (instance.effects = [])).push(effect)
}
}
原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34580.html