iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0
影片教學

Nuxt 3 快速入門系列 第 16

[影片教學] Nuxt 3 狀態管理 (State Management)

  • 分享至 

  • xImage
  •  

Yes

👆建議你可以使用影片子母畫面功能或全螢幕播放來獲得最佳的觀賞體驗,👇下方是本篇教學的相關筆記。


建立路由頁面

pages 目錄下建立一個檔案 ./pages/index.vue

<template>
  <div class="bg-white py-24">
    <div class="flex flex-col items-center">
      <h1 class="text-6xl font-semibold text-gray-800">這裡是首頁</h1>
    </div>
  </div>
</template>

修改 app.vue 頁面:

<template>
  <div>
    <NuxtPage />
  </div>
</template>

可能導致 Hydration mismatch 的頁面

pages/count 目錄下建立一個檔案 ./pages/count/ref.vue

<template>
  <div class="bg-white py-24">
    <div class="flex flex-col items-center">
      <span class="text-9xl font-semibold text-sky-400">{{ count }}</span>
    </div>
  </div>
</template>

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

使用 useState

pages/count 目錄下建立一個檔案 ./pages/count/useState.vue

<template>
  <div class="bg-white py-24">
    <div class="flex flex-col items-center">
      <span class="text-9xl font-semibold text-sky-400">{{ count }}</span>
    </div>
  </div>
</template>

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

修改 app.vue 頁面

<template>
  <div class="bg-white py-24">
    <div class="flex flex-col items-center">
      <h1 class="text-6xl font-semibold text-gray-800">這裡是首頁</h1>
      <div class="my-4 flex flex-col space-y-4">
        <NuxtLink to="/count/ref">前往 /count/ref</NuxtLink>
        <NuxtLink to="/count/useState">前往 /count/useState</NuxtLink>
      </div>
    </div>
  </div>
</template>

跨頁面元件中使用 useState 建立的狀態

pages/counter 目錄下建立一個檔案 ./pages/counter/increment.vue

<template>
  <div class="bg-white py-24">
    <div class="flex flex-col items-center">
      <span class="text-9xl font-semibold text-sky-600">{{ counter }}</span>
      <div class="mt-8 flex flex-row">
        <button
          class="font-base mx-2 rounded-full bg-sky-500 px-4 py-2 text-xl text-white hover:bg-sky-600 focus:outline-none focus:ring-2 focus:ring-sky-400 focus:ring-offset-2"
          @click="counter++"
        >
          增加
        </button>
        <button
          class="font-base mx-2 rounded-full bg-sky-500 px-4 py-2 text-xl text-white hover:bg-sky-600 focus:outline-none focus:ring-2 focus:ring-sky-400 focus:ring-offset-2"
          @click="counter--"
        >
          減少
        </button>
      </div>
      <p class="mt-4 text-slate-500">如果是第一次進入這個頁面,數值初始設定為 0</p>
      <div class="mt-8">
        <NuxtLink to="/">回首頁</NuxtLink>
      </div>
    </div>
  </div>
</template>

<script setup>
const counter = useState('counter', () => 0)
</script>

pages/counter 目錄下建立一個檔案 ./pages/counter/surprise.vue

<template>
  <div class="bg-white py-24">
    <div class="flex flex-col items-center">
      <span class="text-9xl font-semibold text-sky-600">{{ counter }}</span>
      <div class="mt-8 flex flex-row">
        <button
          class="font-base mx-2 rounded-full bg-sky-500 px-4 py-2 text-xl text-white hover:bg-sky-600 focus:outline-none focus:ring-2 focus:ring-sky-400 focus:ring-offset-2"
          @click="counter++"
        >
          增加
        </button>
        <button
          class="font-base mx-2 rounded-full bg-sky-500 px-4 py-2 text-xl text-white hover:bg-sky-600 focus:outline-none focus:ring-2 focus:ring-sky-400 focus:ring-offset-2"
          @click="counter--"
        >
          減少
        </button>
      </div>
      <p class="mt-4 text-slate-500">如果是第一次進入這個頁面,數值初始設定為亂數</p>
      <div class="mt-8">
        <NuxtLink to="/">回首頁</NuxtLink>
      </div>
    </div>
  </div>
</template>

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

調整 app.vue 檔案:

<template>
  <div class="bg-white py-24">
    <div class="flex flex-col items-center">
      <h1 class="text-6xl font-semibold text-gray-800">這裡是首頁</h1>
      <div class="my-4 flex flex-col space-y-4">
        <NuxtLink to="/count/ref">前往 /count/ref</NuxtLink>
        <NuxtLink to="/count/useState">前往 /count/useState</NuxtLink>
        <NuxtLink to="/counter/increment">前往 /counter/increment</NuxtLink>
        <NuxtLink to="/counter/surprise">前往 /counter/surprise</NuxtLink>
      </div>
    </div>
  </div>
</template>

建立自訂的組合式函式來使用 useState

composables/useLocale 目錄下建立一個檔案 ./omposables/useLocale.js

export default function () {
  return useState('locale', () => 'zh-TW')
}

pages 目錄下建立一個檔案 ./pages/locale.vue

<template>
  <div class="bg-white py-24">
    <div class="flex flex-col items-center">
      <p class="mt-4 text-xl text-slate-500">Locale</p>
      <span class="text-6xl font-semibold text-emerald-400">{{ locale }}</span>
    </div>
  </div>
</template>

<script setup>
const locale = useLocale()
</script>

調整 app.vue 檔案:

<template>
  <div class="bg-white py-24">
    <div class="flex flex-col items-center">
      <h1 class="text-6xl font-semibold text-gray-800">這裡是首頁</h1>
      <div class="my-4 flex flex-col space-y-4">
        <NuxtLink to="/count/ref">前往 /count/ref</NuxtLink>
        <NuxtLink to="/count/useState">前往 /count/useState</NuxtLink>
        <NuxtLink to="/counter/increment">前往 /counter/increment</NuxtLink>
        <NuxtLink to="/counter/surprise">前往 /counter/surprise</NuxtLink>
        <NuxtLink to="/locale">前往 /locale</NuxtLink>
      </div>
    </div>
  </div>
</template>

感謝大家的閱讀,歡迎大家給予建議與討論,也請各位大大鞭小力一些:)
如果對這個 Nuxt 3 系列感興趣,可以訂閱接收通知,也歡迎分享給喜歡或正在學習 Nuxt 3 的夥伴。

範例程式碼

參考資料


上一篇
[影片教學] Nuxt 3 資料獲取 (Data Fetching)
下一篇
[影片教學] Nuxt 3 使用 Pinia 進行狀態管理
系列文
Nuxt 3 快速入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言