Nuxt 3 提供一個 composable useState
用來建立元件間的共用響應式狀態,可以當成是 SSR 友善的 ref
,其值會在 SSR 之後保留並在所有元件中共享。
修改 app.vue
。
// app.vue
<template>
<NuxtPage />
</template>
修改 pages/index.vue
。
// index.vue
<template>
<NuxtLink to="counter">counter</NuxtLink>
<br/>
<NuxtLink to="counter2">counter2</NuxtLink>
</template>
在 pages/
新增 counter.vue
。
// pages/counter.vue
<template>
<div>
Counter: {{ counter }}
<button @click="counter++">
+
</button>
<button @click="counter--">
-
</button>
</div>
</template>
<script setup lang="ts">
const counter = useState('counter', () => Math.round(Math.random() * 1000))
</script>
在 pages/
新增 counter2.vue
。
// pages/counter2.vue
<template>
<div>
Counter: {{ counter }}
<button @click="counter++">
+
</button>
<button @click="counter--">
-
</button>
</div>
</template>
<script setup lang="ts">
const counter = useState('counter', () => Math.round(Math.random() * 1000))
</script>
結果如下方影片,我們用 useState
建立一個響應式狀態 counter
,當第一次進入 counter.vue
時會初始化狀態並給一個隨機值,不管增加或減少 counter
的值都會被紀錄下來,而當我們跳轉到 counter2.vue
時因為我們一樣使用了 useState('counter')
所以就會把剛剛已經建立的 counter
拿出來用,而且值也會一樣,這就是 Nuxt 3 的共用響應式狀態。
雖然這樣寫法可以達到共用響應式狀態的目的,但實際在開發上如果這樣寫很不好管理,因為散落在各個檔案裡根本不知道到底建立了哪一些共用響應式狀態,可能會發生在其他頁面已經建立過一樣的名稱但是沒發現導致一直找不到 bug 的情況,所以我們會把共用響應式狀態統一寫在 composables
。
在 composables
裡新增 states.ts
。
// composables/states.ts
export const useCounter = () => useState('counter', () => Math.round(Math.random() * 1000))
修改 pages/counter.vue
和 pages/counter2.vue
。
// pages/counter.vue & pages/counter2.vue
<template>
<div>
Counter: {{ counter }}
<button @click="counter++">
+
</button>
<button @click="counter--">
-
</button>
</div>
</template>
<script setup lang="ts">
const counter = useCounter()
</script>
結果如下,一樣能達到共用的目的,透過組合式函數的自動載入功能讓我們能少寫很多令人煩躁的程式碼,同時在開發時也能更容易管理共用響應式狀態。
ref
前面有提到 useState
是 SSR 友善的 ref
,那如果直接使用 ref
會發生什麼事呢?
修改 composables/states.ts
。
// composables/states.ts
...
export const refCounter = ref(Math.round(Math.random() * 1000))
修改 pages/counter.vue
。
<template>
<div>
Counter: {{ counter }}
<button @click="counter++">
+
</button>
<button @click="counter--">
-
</button>
</div>
</template>
<script setup lang="ts">
const counter = refCounter
</script>
結果如下圖,當我們重新整理的時候會發現畫面上的數字跳了兩次,這是因為 Nuxt 3 的 Universal Rendering 是 SSR + CSR(在 Day 2 – Nuxt 3 核心功能概念(上)有介紹過),所以會在 SSR 時渲染產生一次 refCounter
,之後又在 CSR 時產生一次 refCounter
,而為了避免這個現象才需要用 useState
。
到今天 Nuxt 3 的核心功能概念都介紹差不多了,明天開始會介紹一些 Nuxt 3 好用的 Modules,讓開發更迅速。