From 4c6048651105a1263d9d1c688fc503696353b695 Mon Sep 17 00:00:00 2001 From: dj <1042039504@qq.com> Date: Sun, 8 Feb 2026 15:19:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(computed):=20=E6=B7=BB=E5=8A=A0=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E5=B1=9E=E6=80=A7=E5=8A=9F=E8=83=BD=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现了 ComputedRefImpl 类来管理计算属性 - 添加了 computed 函数用于创建计算属性 - 在 ReactiveEffect 中添加 computed 属性引用 - 将 computed 导出到 reactivity 和 vue 主包 - 添加了 isFunction 工具函数判断函数类型 - 创建了计算属性的 HTML 示例文件进行演示 --- packages/reactivity/src/computed.ts | 30 +++++++++++++++++++ packages/reactivity/src/effect.ts | 2 ++ packages/reactivity/src/index.ts | 1 + packages/shared/src/index.ts | 4 +++ .../vue/examples/reactivity/computed.html | 26 ++++++++++++++++ packages/vue/src/index.ts | 2 +- 6 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 packages/reactivity/src/computed.ts create mode 100644 packages/vue/examples/reactivity/computed.html diff --git a/packages/reactivity/src/computed.ts b/packages/reactivity/src/computed.ts new file mode 100644 index 0000000..ef79bb1 --- /dev/null +++ b/packages/reactivity/src/computed.ts @@ -0,0 +1,30 @@ +import { isFunction } from '@vue/shared' +import { Dep } from './dep' +import { ReactiveEffect } from './effect' +import { trackRefValue } from './ref' + +export class ComputedRefImpl { + public dep?: Dep = undefined + private _value!: T + public readonly effect: ReactiveEffect + public readonly __v_isRef = true + constructor(getter) { + this.effect = new ReactiveEffect(getter) + this.effect.computed = this + } + get value() { + trackRefValue(this) //触发依赖 + this._value = this.effect.run() + return this._value + } +} + +export function computed(getterOrOptions) { + let getter + const onlyGetter = isFunction(getterOrOptions) + if (onlyGetter) { + getter = getterOrOptions + } + const cRef = new ComputedRefImpl(getter) + return cRef +} diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 7c40214..510db96 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -1,5 +1,6 @@ import { createDep, Dep } from './dep' import { isArray } from '@vue/shared' +import { ComputedRefImpl } from './computed' type KeyToDepMap = Map /** @@ -19,6 +20,7 @@ export function effect(fn: () => T) { export let activeEffect: ReactiveEffect | undefined export class ReactiveEffect { + computed?: ComputedRefImpl constructor(public fn: () => T) {} run() { //当前被激活的effect实例 diff --git a/packages/reactivity/src/index.ts b/packages/reactivity/src/index.ts index 7a869fe..7964e45 100644 --- a/packages/reactivity/src/index.ts +++ b/packages/reactivity/src/index.ts @@ -1,3 +1,4 @@ export { reactive } from './reactive' export { effect } from './effect' export { ref } from './ref' +export { computed } from './computed' diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 480fe58..97d9207 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -9,3 +9,7 @@ export const isObject = (val: unknown) => */ export const hasChanged = (value: any, oldValue: any): boolean => !Object.is(value, oldValue) + +export const isFunction = (val: unknown): val is Function => { + return typeof val === 'function' +} diff --git a/packages/vue/examples/reactivity/computed.html b/packages/vue/examples/reactivity/computed.html new file mode 100644 index 0000000..a53b3e8 --- /dev/null +++ b/packages/vue/examples/reactivity/computed.html @@ -0,0 +1,26 @@ + + + + + Document + + + +
+ + + \ No newline at end of file diff --git a/packages/vue/src/index.ts b/packages/vue/src/index.ts index 015eeb1..6a2f477 100644 --- a/packages/vue/src/index.ts +++ b/packages/vue/src/index.ts @@ -1 +1 @@ -export { reactive, effect, ref } from '@vue/reactivity' +export { reactive, effect, ref, computed } from '@vue/reactivity'