QWIK DOCS / V2

性能实践

把读取放对位置,让 Qwik 的细粒度更新真正生效。

约 2 分钟Qwik v217 / 19
本页目录4 节
  1. 在模板里读取,而不是提前计算
  2. 把 useVisibleTask$ 当逃生舱
  3. 不要在浏览器里读位置
  4. 其他小规则

Qwik 的性能来自精确的订阅:谁读取了状态,状态变化时就只更新谁。写法会直接决定订阅的范围。以下几条规则能避免把细粒度更新变回整页重渲染。

01在模板里读取,而不是提前计算#

tsx不推荐
const count = useSignal(0);
const label = count.value > 0 ? '正数' : '零或负数';

return <div>{label}</div>;
tsx推荐
const count = useSignal(0);

return (
  <div>
    {count.value > 0 ? '正数' : '零或负数'}
  </div>
);

组件函数内读取 signal 会让整个组件成为订阅者。把读取放进 JSX,订阅范围缩小到具体的 DOM 节点。派生值较复杂时,用 useComputed$() 把计算与订阅隔离。

tsxcode
const count = useSignal(0);
const doubled = useComputed$(() => count.value * 2);

return <output>{doubled.value}</output>;

02把 useVisibleTask$ 当逃生舱#

useVisibleTask$() 会急切执行并阻塞主线程,它应当是最后手段。多数需求有更轻的替代:

需求替代方案
监听元素事件useOn() 或 JSX 上的 onClick$
监听 window / documentuseOnWindow() / useOnDocument()
响应状态变化useTask$() + track()
只需要执行一次的客户端逻辑useOn('qidle') 或 useOn('qvisible')
读取路由信息useLocation()
tsx用 useOnDocument 代替手动绑定
useOnDocument(
  'mousemove',
  $((event) => {
    pointer.value = {
      x: (event as MouseEvent).clientX,
      y: (event as MouseEvent).clientY,
    };
  })
);

这样监听器只在事件真正发生时加载,而不是页面一出现就下载并执行。

03不要在浏览器里读位置#

window.location 只存在于客户端。用 useLocation() 可以在 SSR 阶段就拿到同样的信息,把分支渲染进 HTML,而不是等到浏览器再补。

tsxcode
const loc = useLocation();

if (loc.url.pathname.startsWith('/docs')) {
  // 服务端与客户端行为一致
}

04其他小规则#

  • 状态尽量靠近使用它的组件,避免在根组件创建所有 signal。
  • 需要共享时优先用 context,而不是层层传参。
  • 列表项作为独立组件,读取各自的数据,避免父级订阅整个数组。
  • 图片与字体是首屏大头,框架再快也救不了巨大的资源。
  • 生产环境验证:dev 下的 chunk 数量与预取行为都和线上不同。