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配置(挂载到根节点)。