跳转到内容

性能与订阅策略

性能优化的核心不是“少写代码”,而是“让订阅边界对齐真实变化边界”。

这篇文档解决三个问题:

  • 订阅谁:根节点、路径 Unit,还是 selector?
  • 什么时候合并写入:batch / commit
  • 如何快速定位过度渲染。
场景推荐原因
已有明确路径(如 store.user.nameuseIO(pathUnit)订阅最小,更新最精准
需要投影少量字段useIOSelector(store, selector)保持结构化建模并控制渲染范围
小组件直接读取完整值useIO(store)写法简单,认知成本低
一次动作内多处写入batchcommit合并通知,减少中间态渲染
const name = useIO(userStore.profile.name);
const view = useIOSelector(store, (s) => ({
count: s.count,
parity: s.count % 2,
}));

若 selector 返回对象,建议提供 isEqual

const parity = useIOSelector(store, (s) => ({ p: s.count % 2 }), {
isEqual: (prev, next) => prev.p === next.p,
});
batch(() => {
store.form.name.set('Ada');
store.form.email.set('ada@example.com');
store.ui.dirty.set(true);
});
  • 列表项组件订阅整个根对象。
  • selector 每次返回新对象,但未提供 isEqual
  • 同一交互触发多次离散 set,未做合并。
  • 重置整数组后仍持有旧路径 Unit 进行订阅。
  1. 找到频繁重渲染组件,确认它订阅的 Unit/selector。
  2. 将“根订阅”收敛到“路径订阅”。
  3. 给对象型 selector 增加 isEqual
  4. 把同一交互内的多次写入改为 batch/commit
  5. 用 DevTools 对照 patch 流验证优化是否生效。