最佳實務
在模板中內嵌操作
如果操作在模板中內嵌,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
}
}
})
許多與位置資訊相關的操作都可以在初始伺服器端渲染期間執行,從而產生沒有任何 JavaScript 開銷的純 HTML。
強制在用戶端執行此邏輯會增加前期 JavaScript 並導致急切載入。
// Do this!
const location = useLocation();
if (location.url.href.includes('foo')) {
// Do the thing
}
例外
當對純靜態檔案使用 SSG 時,在建構時不可避免地需要依賴沒有目前位置資訊的伺服器。
但是,請謹慎操作!如果在使用者事件發生之前不需要所需資訊(例如查詢參數),請將檢查納入您的事件處理程式碼中。
這種方法有助於防止急切載入 JavaScript 並提高效能。
請參閱:useLocation() 文件