iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0
Vue.js

Nuxt.js 3.x 筆記-打造 SSR 專案系列 第 19

D19:Nuxt 3.x 狀態管理 State Management (1)-useState

  • 分享至 

  • xImage
  •  

本篇文章同步更新於個人部落格,歡迎交流指教~謝謝您的閱讀

專案開發過程中常會有狀態共享的需求。父子元件間資料傳遞可以使用 Props 和 $emit,或是 Provide 和 Inject(參考文章),Nuxt2 使用 VueX 管理工具搭配 vuex-persistedstate 保存狀態(參考文章),接下來說明如何在 Nuxt3 利用更便利高效的方式管理共享狀態。

狀態管理預計分為以下三篇說明,本篇將介紹 useState

  1. useState: Nuxt Composable
  2. Pinia: Vue.js 狀態管理工具
  3. pinia-plugin-persistedstate: 維持 Store 狀態

useState

useState 是 Nuxt3 提供的 Composable,適合用來建立響應式、伺服器端友善(SSR-friendly)的共享狀態

會特別提到 SSR-friendly,要先理解 Nuxt Universal 渲染模式(server-side + client-side),由伺服器端預先載入 HTML,並傳給瀏覽器,接著由瀏覽器載入完整的 Javascript 並執行,至此網頁才具有互動性。
因此,若在頁面上定義響應式動態資料如下:

<template>
  <div>
    {{ count }}
	</div>
</template>

<script setup>
const count = ref(Math.round(Math.random() * 1000));
</script>

瀏覽器會拋出警告:Hydration text content mismatch
原因是在伺服器端預先渲染出來的 count,跟瀏覽器後來執行 JS 運算出來的結果不同

useState 參數:

  • key: 唯一值,避免重複取得資料(前面提到的 Hydration 問題),如果沒帶入,useState 會自動生成
  • init: 回傳初始值的函式,會回傳一個 ref 物件
  • T: 使用 TypeScript 型別
useState<T>(key: string, init?: () => T | Ref<T>): Ref<T>

useState 共享狀態

<template>
  <div>
    {{ counter }}
  </div>
</template>

<script setup>
const counter = useState('counter', () => Math.round(Math.random() * 1000));
</script>

其他頁面使用 useState('counter') 可以同步取得/更新狀態

<template>
  <div>
    {{ counter }}
    <button @click="counter++">+</button>
    <button @click="counter--">-</button>
  </div>
</template>

<script setup>
const counter = useState('counter', () => Math.round(Math.random() * 1000));
</script>

注意:若直接使用 const counter = useState('counter') 取值,而 useState('counter') 尚未被賦值,可能會發生錯誤,可以使用以下方法定義預設值

useState 搭配 Composables 全域共享狀態

將狀態定義在 Composables,可以定義預設值,並在頁面間共享狀態

名稱自訂,範例使用 composables/state.js

export const useCounter = () => useState('counter', () => Math.round(Math.random() * 1000));

頁面使用 useCounter() 取值(等同於 useState('counter')),並可更新狀態

<template>
  <div>
    {{ counter }}
    <button @click="counter++">+</button>
    <button @click="counter--">-</button>
  </div>
</template>

<script setup>
const counter = useCounter();
</script>

clearNuxtState 清除狀態

使用 clearNuxtState(key) 清除當前儲存的狀態

<template>
  <div>
    {{ counter }}
    <button @click="clearCounter()">clear</button>
  </div>
</template>

<script setup>
const counter = useCounter();
const clearCounter = () => {
  clearNuxtState('counter');
};
</script>

參考資源:
https://nuxt.com/docs/getting-started/state-management
https://ithelp.ithome.com.tw/articles/10302323


上一篇
D18:Nuxt 3.x 搭配 CSS Framework-以 Bootstrap 5 為例
下一篇
D20:Nuxt 3.x 狀態管理 State Management (2)-Pinia
系列文
Nuxt.js 3.x 筆記-打造 SSR 專案30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言