性能实践
把读取放对位置,让 Qwik 的细粒度更新真正生效。
Qwik 的性能来自精确的订阅:谁读取了状态,状态变化时就只更新谁。写法会直接决定订阅的范围。以下几条规则能避免把细粒度更新变回整页重渲染。
01在模板里读取,而不是提前计算#
const count = useSignal(0);
const label = count.value > 0 ? '正数' : '零或负数';
return <div>{label}</div>;const count = useSignal(0);
return (
<div>
{count.value > 0 ? '正数' : '零或负数'}
</div>
);组件函数内读取 signal 会让整个组件成为订阅者。把读取放进 JSX,订阅范围缩小到具体的 DOM 节点。派生值较复杂时,用 useComputed$() 把计算与订阅隔离。
const count = useSignal(0);
const doubled = useComputed$(() => count.value * 2);
return <output>{doubled.value}</output>;02把 useVisibleTask$ 当逃生舱#
useVisibleTask$() 会急切执行并阻塞主线程,它应当是最后手段。多数需求有更轻的替代:
| 需求 | 替代方案 |
|---|---|
| 监听元素事件 | useOn() 或 JSX 上的 onClick$ |
| 监听 window / document | useOnWindow() / useOnDocument() |
| 响应状态变化 | useTask$() + track() |
| 只需要执行一次的客户端逻辑 | useOn('qidle') 或 useOn('qvisible') |
| 读取路由信息 | useLocation() |
useOnDocument(
'mousemove',
$((event) => {
pointer.value = {
x: (event as MouseEvent).clientX,
y: (event as MouseEvent).clientY,
};
})
);这样监听器只在事件真正发生时加载,而不是页面一出现就下载并执行。
03不要在浏览器里读位置#
window.location 只存在于客户端。用 useLocation() 可以在 SSR 阶段就拿到同样的信息,把分支渲染进 HTML,而不是等到浏览器再补。
const loc = useLocation();
if (loc.url.pathname.startsWith('/docs')) {
// 服务端与客户端行为一致
}04其他小规则#
- 状态尽量靠近使用它的组件,避免在根组件创建所有 signal。
- 需要共享时优先用 context,而不是层层传参。
- 列表项作为独立组件,读取各自的数据,避免父级订阅整个数组。
- 图片与字体是首屏大头,框架再快也救不了巨大的资源。
- 生产环境验证:dev 下的 chunk 数量与预取行为都和线上不同。