最佳实践
模板中的内联操作
如果操作在模板中内联,Qwik 优化器可以更好地优化应用程序的响应性。
// Don't do this!
export default component$(() => {
const signal = useSignal(0);
const isBiggerThanZero = signal.value > 0 ? 'Bigger than zero' : 'Smaller than zero';
return (
<div>
<button onClick$={() => signal.value++}>+</button>
<button onClick$={() => signal.value--}>-</button>
<div>{isBiggerThanZero} - Current value: { signal.value }</div>
</div>
);
});
上面的实现将在信号更改时导致整个模板重新渲染。这是因为 isBiggerThanZero
没有在模板中内联。
export default component$(() => {
const signal = useSignal(0);
return (
<div>
<button onClick$={() => signal.value++}>+</button>
<button onClick$={() => signal.value--}>-</button>
<div>
{signal.value > 0 ? 'Bigger than zero' : 'Smaller than zero'} - Current
value: {signal.value}
</div>
</div>
);
});
useTask$
或 useComputed$
将信号读取移动到 这与上面的提示类似。
每次 Qwik “读取” 信号/存储值时,“读取”发生所在的函数将在该信号的每次更改时重新运行。
因此,尽可能在 useTask$
或 useComputed$
函数内部而不是组件函数内部“读取”值(并跟踪它们)。
因为否则,您的组件函数将在每次更改时重新运行。
// Don't do this!
export default component$(() => {
const count = useSignal(1);
const doubleCount = count.value*2;
return (
<div>{doubleCount}</div>
);
});
上面的实现将在信号更改时导致整个模板重新渲染。
下面,只有 useComputed$
函数将在任何 count.value
更改时重新运行
export default component$(() => {
const count = useSignal(1);
const dobuleCount = useComputed$(() => count.value*2);
return (
<div>{doubleCount.value}</div>
);
});
useVisibleTask$()
作为最后的手段
将 虽然方便,但 useVisibleTask$()
会急切地运行代码并阻塞主线程,阻止用户交互,直到任务完成。您可以将其视为一个应急措施。
如有疑问,请勿使用 “useVisibleTask$()”,而是使用
useTask$()
-> 在 SSR 模式下执行代码。useOn()
-> 监听当前组件
根元素上的事件。useOnWindow()
-> 监听window
对象上的事件。useOnDocument()
-> 监听document
对象上的事件。
但有时,这是实现结果的唯一方法。
在这种情况下,您可以在 “useVisibleTask$” 之前的行添加 // eslint-disable-next-line qwik/no-use-visible-task
来消除警告。
useOn()
、useOnWindow()
或 useOnDocument()
注册 DOM 事件
使用 Qwik 允许使用 useOn()
或使用 JSX 以声明方式注册事件监听器。
当使用 useVisibleTask$()
以编程方式注册事件时,我们正在急切地下载和执行 JavaScript,即使事件没有触发。
// Don't do this!
useVisibleTask$(({ cleanup }) => {
const listener = (event) => {
const mouseEvent = event as MouseEvent;
console.log(mouseEvent.x, mouseEvent.y);
};
document.addEventListener('mousemove', listener);
cleanup(() => {
document.removeEventListener('mousemove', listener);
});
});
上面的实现会导致更多 JavaScript 急切地加载,而不是对用户事件做出精确响应。增加的前端 JavaScript 加载会导致应用程序性能下降。
相反,使用 useOnDocument()
钩子在 document
对象上注册事件,这样 Qwik 只有在事件触发时才会执行任何 JS。
useOnDocument(
'mousemove',
$((event) => {
const mouseEvent = event as MouseEvent;
console.log(mouseEvent.x, mouseEvent.y);
// No manual clean up required!
})
);
window
对象访问位置
避免从 不要直接访问 window.location
,而是使用 useLocation()
钩子。
// Don't do this!
useVisibleTask$(()=> {
if (window.location.href).includes('foo') {
//... do the thing
}
})
// or
useTask$(() => {
if (isBrowser) {
if (window.location.href).includes('foo') {
//... do the thing
}
}
})
许多与位置信息相关的操作可以在初始服务器端渲染期间执行,从而生成纯 HTML,而无需任何 JavaScript 开销。
强制此逻辑在客户端运行会导致增加的前端 JavaScript 并导致急切加载。
// Do this!
const location = useLocation();
if (location.url.href.includes('foo')) {
// Do the thing
}
例外
当使用 SSG 生成纯静态文件时,在构建时间内不可避免地要依赖服务器,而没有当前位置信息。
但是,请谨慎!如果所需信息(例如查询参数)直到用户事件发生才需要,请将检查包含在您的事件处理代码中。
这种方法有助于防止 JavaScript 的急切加载并提高性能。