iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
Vue.js

Nuxt 3 初學者指南:30天從基礎到實踐系列 第 6

Day 6 – Nuxt 3 Composables(組合式函數)

  • 分享至 

  • xImage
  •  

Composables 是 Vue 3 Composition API 的重要概念,將共用的有狀態邏輯(stateful logic)寫成一個可重用的函式以提高可維護性與測試性,在 Nuxt 3 使用時並無須手動引入(Auto-imports 👍)。

built-in Composables

Nuxt 3 預設有多組內建的 Composables,詳細內容可參考官方文件,以下舉幾個常見的例子。

useNuxtApp

提供了一種 Nuxt 執行時存取 context 的方法,在伺服器端與客戶端都可以使用,且幫助我們存取 Vue 實體、Hooks、設定值與其他內部狀態等。

// app.vue
const nuxtApp = useNuxtApp()
console.log(nuxtApp)

https://ithelp.ithome.com.tw/upload/images/20230920/20162805IQZ9N9eqvY.png

useNuxtApp 常見的方法如:provide (name, value)

// app.vue
const nuxtApp = useNuxtApp()
nuxtApp.provide('hello', (name) => `Hello ${name}!`)
console.log(nuxtApp.$hello('Kitty'))

Server-Side

https://ithelp.ithome.com.tw/upload/images/20230920/20162805MTIP4vVNU4.png

Client-Side

https://ithelp.ithome.com.tw/upload/images/20230920/20162805MdPOpDCigR.png

useCookie

提供如同 document.cookie 的功能,可以讓 Web 伺服器記住使用者的狀態資訊(ex:登入者的 token、購物車或喜愛商品)。

// app.vue
<template>
  <div>
    <h1>Counter: {{ counter }}</h1>
    <button @click="counter = null">reset</button>
    <button @click="counter--">-</button>
    <button @click="counter++">+</button>
  </div>
</template>
// app.vue
<script setup lang="ts">
  const counter = useCookie('counter')
  counter.value = 0
</script>

瀏覽器畫面顯示。

https://ithelp.ithome.com.tw/upload/images/20230920/20162805qlktxD1wr9.png

已建立名稱為 counter 的 cookie,且值為 0。

https://ithelp.ithome.com.tw/upload/images/20230920/201628050akF7MYoPz.png

useCookie('counter') 表使用名稱為 counter 的 cookie。 但須注意此處不代表就建立 counter 的 cookie,而是需要 counter.value = 0,賦值之後才會建立,如果少了這段,counter--counter++ 會出現錯誤 NAN

https://ithelp.ithome.com.tw/upload/images/20230920/20162805u6BzmyGYC8.png

如果希望在 useCookie 直接加上預設值也是可以的,只需在後面加上 default 值。

const counter = useCookie('counter', {
  default: () => 0,
})

清除 cookie 只需 counter = null,cookie 就會被刪除。

⚠ 注意:官方文件有說明 "useCookie only works during setup or Lifecycle Hooks.",如果在自定義的 composables/ 或其他地方使用 useCookie,重新渲染畫面可能會出現 cookie 回到預設值的問題。

此處僅稍微帶過 useCookie 的使用方式,關於如何設定 cookie 的 maxAgehttpOnlydomain ... 等,可以參考 useCookie

🌞 其他還有像 useFetchuseRouteuseState ... 等常用且重要的 composables 未來會陸續出現在每一天的文章中

https://ithelp.ithome.com.tw/upload/images/20230920/20162805GP96xVuK56.png

建立自訂的 Composables

如果要建立自訂的 Compsables 可以參考以下步驟。

Step 1

建立 composables/ 資料夾。

Step 2

建立 Composables:

  1. 方法一:使用具名導出

    // composables/useMouseX.ts
    export const useMouseX = () => {
      const x = useState('x', () => 0)
      const Update = (event: any) => {
        x.value = event.pageX
      }
      onMounted(() => window.addEventListener('mousemove', Update))
      onUnmounted(() => window.removeEventListener('mousemove', Update))
      return { x }
    }
    
  2. 方法二:使用預設導出

    // composables/useMouseY.ts
    export default function () {
      const y = useState('y', () => 0)
      const Update = (event: any) => {
        y.value = event.pageY
      }
      onMounted(() => window.addEventListener('mousemove', Update))
      onUnmounted(() => window.removeEventListener('mousemove', Update))
      return { y }
    }
    

    使用時 Nuxt 會自動轉換成該檔名的 camelCase 形式(不包含副檔名),例如上述範例若將 useMouseY.ts 改為 use-mouseY.ts,使用時仍然是 useMouseY()

Step 3

現在可以在 .js.ts.vue 檔案中使用自動引入的 Composables。

//app.vue
<template>
  <h1>游標座標</h1>
  <h2>x: {{ x }}</h2>
  <h2>y: {{ y }}</h2>
</template>
// app.vue
<script setup lang="ts">
  const { x } = useMouseX()
  const { y } = useMouseY()
</script>

Nested Composables

Nuxt 只會掃描在 composables/ 目錄下的頂層檔案,範例如下:

composables        掃描
 ┣ index.ts        ✅            
 ┣ useCounter.ts   ✅ 
 ┗ mouse    
   ┣ useMouseX.ts  ❌   
   ┗ useMouseY.ts  ❌   

⭐ Nuxt 3 提供兩個方式使得在巢狀結構內的 composables 也可以被 Nuxt 掃描:

  1. (推薦)在 composables/index.ts 重新導出:

    // composables/index.ts
    export { useMouseX } from './mouse/useMouseX.ts'
    
  2. 修改 nuxt.config.ts 中的設定:

    // nuxt.config.ts
    export default defineNuxtConfig({
      imports: {
        dirs: [
          // 掃描頂層模組
          'composables',
    
          // 掃描特定名稱和副檔名的第一層模組
          'composables/*/index.{ts,js,mjs,mts}',
    
          // 或掃描指定目錄中的所有模組
          'composables/**'
        ]
      }
    })
    

🌞 Upcoming

今天提到的 Composables 是將有狀態邏輯寫成一個可重用的函式,那麼我們該如何建立共用的無狀態邏輯(Stateless Logic)函式?該存放在哪個資料夾中呢?明日揭曉!


參考資料

Vue Composables
useNuxtApp


上一篇
Day 5 – Nuxt 3 目錄結構
下一篇
Day 7 – Nuxt 3 Utils(實用函式)
系列文
Nuxt 3 初學者指南:30天從基礎到實踐30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言