Nuxt 3 開發心得 — 比較 Pinia、useState
最近陸續接觸到了 Nuxt 3 的專案,不可避免地在開發時遇到了必須在多個 Component 之間傳遞資料的需求,這篇文章將會簡單介紹在 Nuxt 3 最常使用到的 2 種跨元件資料傳遞方式。
Pinia
不論是官方文件或是各種教學文章,一定會提到在 Nuxt 3 如果要使用 Pinia 作為跨元件的儲存套件,這邊我就不贅述安裝設定之類的步驟了,僅會提出用法與一些注意事項。
這裡,我們會以購物車作為範例。
定義一個 Store
我們需要先使用 defineStore()
定義一個 Store,而這一個定義的 Store 就跟命名變數一樣,需要替它命一個具有唯一性的名字。
// 範例:購物車的 Store
export const useCartStore = defineStore('storeCart', () => {
// 這裡放購物車的商品
}
設定 State
當我們定義完成 Store 後,接著來放一些資料吧
// 範例:購物車的 Store
export const useCartStore = defineStore('storeCart', () => {
// 這裡放購物車的商品
const product = ref([])
return {
product
}
}
設定 Action
Pinia 有一個跟 Vuex 不同的地方,差異處在於 Pinia 沒有 Mutation,如果需要去改變 State 的值的時候,可以透過 Action 去實作。
// 範例:購物車的 Store
export const useCartStore = defineStore('storeCart', () => {
// 這裡放購物車的商品
const product = ref([])
// 這裡放增加商品的方法
const addProduct = (value) => {
product.value.push(value)
}
return {
product,
addProduct
}
}
useState
useState 是包含在 Nuxt 3 原生的 Composable,因此不需要再額外安裝套件即可馬上使用,而且能夠建立 SSR-friendly 的共享狀態,在部分情境下,使用 useState 會是個更好的選擇。
其實 useState 最主要用來解決的是 server-side 跟 client-side 經過 Javascript 渲染時資料不同的問題。
<template>
<div>
{{ random }}
</div>
</template>
<script setup>
const random = ref(Math.round(Math.random() * 100));
</script>
由於,HTML 的部分包含了 random 的變數,因此在 server-side 執行渲染 HTML 傳到瀏覽器的時候,會先經過一次 Math.random()
的過程,
而到 client-side 的時候載入了完整的 Javascript 此時又會再經過一次 Math.random()
的過程,此時會造成 random
的數值不相同。
這個狀況發生的時候,我們會在 console 看見錯誤警告 Hydration text content mismatch
。
Hydration 的中文翻譯叫「水合、補水」,字面上的意義比較艱澀,可以想像 server-side 跟 client-side 分別負責了兩件事, server-side 就是在產生模具,client-side 就是將資料、Javascript 注入這個產生好的模具中,使用這個詞來形容這個過程確實蠻生動的。
既然 useState
是要用來解決 Hydration 問題的,那為什麼能夠作為共享資料的方式呢?
沒錯,就是透過搭配 Composables
來達成的。
我們可以先建立一個 complsables/useRandom.js
export const useRandom = () => {
const random = useState('random', () => Math.round(Math.random() * 100))
return {
random
}
}
而在頁面或者 component 中使用 useRandom
來取得資料
<template>
<div>
{{ random }}
</div>
</template>
<script setup>
const { random } = useRandom();
</script>
透過這種方式,就可以在全域共享狀態,同時省去擔心 Hydration 的問題。
結論心得
使用 Nuxt 3 開發的時候,跟使用 Vue 3 / Composition API 開發的時候,大多數的開發體驗是相似的,但在開發 Nuxt 3 的初期,會發現自己偶爾會碰到 Hydration 的錯誤訊息,當時並沒有非常深刻理解這個觀念,也是到後來比較有時間才有機會重新學習這個觀念。
全域狀態管理是個很方便的工具,但同時也會有一些問題衍伸,因此選擇當下最適切的作法來去處理狀態管理是個相當重要的課題。