Skip to content

useComputedObject

在组件中动态创建计算属性对象ComputedObject)的 Hook。

useComputed的区别:useComputedObject返回计算属性对象本身(不订阅值变化、不触发重渲染),由开发者自行决定如何使用(手动watch、传给信号组件等);useComputed则额外订阅值变化驱动组件重渲染。

签名

ts
interface UseComputedObjectType<State extends Dict> {
    // getter 函数(同步或异步)
    <Value>(getter: ComputedGetter<Value, Scope> | AsyncComputedGetter<Value, Scope>,
        computedOptions?: ComputedOptions<Value, Scope>
    ): SyncComputedObject<Value, Scope> | AsyncComputedObject<Value, Scope> | undefined;
    // builder:computed(...) / asyncComputed(...)
    <Value, Scope>(builder: ComputedDescriptorBuilder<Value, Scope>,
        computedOptions?: ComputedOptions<Value, Scope>
    ): SyncComputedObject<Value, Scope> | AsyncComputedObject<Value, Scope> | undefined;
}

返回值: 计算属性对象,主要成员:

成员 说明
value 当前计算结果
async 是否为异步计算
id 计算对象唯一标识
watch(listener) 订阅值变化,返回Watcher
run() 手动触发计算
detach() 从 store 分离并销毁

使用说明

  • 首次渲染时创建计算属性对象,组件卸载时自动detach()
  • 默认注入scope: ObserverScopeRef.Root(动态创建的计算属性没有"所在对象",统一挂到根节点)。
  • useComputed的底层实现。

示例

tsx
const { useComputedObject } = createStore({
    order: { price: 100, count: 2 },
});

const totalObj = useComputedObject((state) => state.order.price * state.order.count);

// 手动订阅值变化
useEffect(() => {
    const watcher = totalObj?.watch(() => {
        console.log('total =', totalObj.value);
    });
    return () => watcher?.off();
}, []);

// 手动触发重新计算
<Button onClick={() => totalObj?.run()}>重新计算</Button>

运行效果如下:

loading

注意事项

不订阅值变化

useComputedObject返回的对象值变化不会触发组件重渲染。需要驱动渲染时请使用useComputed,或自行通过watch + setState实现。

TIP

useComputedObject内部基于useObserverObject实现(该 API 不对外公开),仅追加默认scope配置(挂载到根节点)。