# 🏅 Day 18 - Nuxt3 插件 ( Plugins ) - 整合 Vue3 插件 ## 今日學習目標 - 學習在 Nuxt3 中整合 Vue3 插件 - 學習使用 defineNuxtPlugin 掛載第三方插件和全域註冊元件 ## 前言 在 Day17 的學習中,我們經由 `nuxtApp.vueApp` 在 Vue 的實體中新增了全域的自定義指令。 除了實作自定指令以外,`nuxtApp.vueApp` 也可以用來整合外部第三方插件的功能和元件,接下來將介紹 Nuxt3 如何整合 Vue3 插件。 ## Vue3 插件的整合 在 Vue、Vue CLI 或 Vite 中,通常會在進入點檔案(如 `index.js` 或 `main.js`)使用 [app.use()](https://vuejs.org/guide/reusability/plugins.html) 來安裝外部插件,並使用 [app.component()](https://vuejs.org/guide/components/registration.html#global-registration) 註冊外部插件的 Vue 元件。 ```jsx // Vue、Vue CLI、Vite 環境 const app = createApp(App); // 安裝外部插件 ( 全域 ) app.use(外部插件,{ /* 傳遞給插件的選項 */ }); // 註冊全域元件 app.component('外部元件名稱', { /* 元件的結構 */ }); //將 app 掛載到容器元素 <div id="app"> </app> app.mount('#app'); ``` 然而,Nuxt3 沒有 `index.js` 或 `main.js` 作為進入點檔案,因此整合外部插件的功能以及註冊插件的元件需要放置在 `/plugins` 資料夾中,通過 Nuxt3 插件系統實現。 ## Nuxt3 整合 Vue3 插件 這裡將以 [vue3-colorpicker](https://github.com/aesoper101/vue3-colorpicker) 插件為範例,根據 [文件](https://github.com/aesoper101/vue3-colorpicker/blob/main/README.ZH-cn.md) 的安裝步驟與 Nuxt3 整合。 ### 步驟一. 安裝插件 使用 npm 或 yarn 安裝 `vue3-colorpicker`: ```jsx npm install vue3-colorpicker // 或是使用 yarn yarn add vue3-colorpicker ``` ### 步驟二. 建立 Nuxt 插件 在 `/plugins` 資料夾內建立 `colorpicker.client.js` 。透過 `nuxtApp`參數操作 Vue 實體,使用 `.use()` 方法將 vue3-colorpicker 插件的 Vue3ColorPicker 註冊到全域的 Vue 實體中。`nuxtApp.vueApp.use()` 的參數與 Vue3 的 [app.use()](https://vuejs.org/api/application.html#app-use) 格式相同,第一個參數為插件本體,第二個參數為傳遞給插件的選項(非必需)。 ```jsx // plugins/colorpicker.client.js import Vue3ColorPicker from "vue3-colorpicker"; import "vue3-colorpicker/style.css"; export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.use(Vue3ColorPicker); }); ``` 除了使用 `use()` 註冊插件以外,另外一種方式是具名匯入 `vue3-colorpicker` 的 `ColorPicker` 元件結構,使用 `nuxtApp.vueApp.component()` 將其全域註冊。 `component()` 的參數格式與 Vue3 的 [app.component()](https://vuejs.org/api/application.html#app-component) 相同,第一個參數為元件名稱,第二個參數為元件本身。 ```jsx import { ColorPicker } from "vue3-colorpicker"; import "vue3-colorpicker/style.css"; export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.component("ColorPicker", ColorPicker); }); ``` 另外需注意,因為插件中涉及 DOM 操作,而伺服器端環境無法執行瀏覽器的 DOM ( 如 `HTMLElement`、`window`、`document` 等 ),所以需要在檔案名稱加入 `.client` 後綴,調整成 `colorpicker.client.js` 確保僅在客戶端執行,避免下圖 `HTMLElement is not defined` 的錯誤。  ### 步驟三. 在模板中使用元件 在 `/pages/index.vue` 中加入 `<ColorPicker />` 元件,並在父層加入一層 [<ClientOnly></ClientOnly>](https://nuxt.com/docs/api/components/client-only) 元件,確保 `<ColorPicker />` 元件只會在客戶端進行渲染。 ```jsx <script setup> const pureColor = ref("green"); const gradientColor = ref( "linear-gradient(0deg, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 1) 100%)" ); </script> <template> <ClientOnly> <ColorPicker v-model:pureColor="pureColor" v-model:gradientColor="gradientColor" /> </ClientOnly> </template> ``` 加入 `<ClientOnly>` 的原因是,當插件檔案使用 `.client` 後綴時,該插件僅在客戶端執行。 因此 `<ColorPicker />` 元件也僅需在客戶端渲染,不應在伺服器端渲染。若不加入 `<ClientOnly>`,會出現 `Hydration node mismatch` 的問題,即伺服器端渲染與客戶端渲染不一致。例如,下圖是未使用 `<ClientOnly>` 時的警告,伺服器端渲染出的 HTML 為空,而客戶端渲染的 HTML 則正常。  <br> > 今日學習的[範例 Code - 資料夾: day18-plugin-use-example](https://github.com/hexschool/nuxt-daily-tasks-2024) ## 題目 請 fork 這一份 [模板](https://github.com/jasonlu0525/nuxt3-live-question/tree/day18-plugin-use?tab=readme-ov-file) ,完成以下條件 : - 在 `plugins/loading.js` 中使用 Nuxt3 插件系統整合 [vue-loading-overlay](https://www.npmjs.com/package/vue-loading-overlay) 套件。 - 套件整合後,在 `/pages/index.vue` 中透過按鈕點擊的方式開啟與關閉讀取效果。 ## 回報流程 將答案上傳至 GitHub 並複製 GitHub repo 連結貼至底下回報就算完成了喔 ! 解答位置請參考下圖(需打開程式碼的部分觀看)  <!-- 解答 : https://github.com/jasonlu0525/nuxt3-live-answer/tree/day18-plugin-use --> 回報區 --- | # | Discord | Github / 答案 | | --- | ----- | ----- | | 1 | dragon |[Github](https://github.com/peterlife0617/2024-nuxt-training-homework01/tree/feature/day18)| | 2 | 眼睛 |[Github](https://github.com/Thrizzacode/nuxt3-live-question/tree/day18-plugin-use)| | 3 | kevinhes |[Github](https://github.com/kevinhes/nuxt-daily-mission/tree/day18)| | 4 | hsin yu |[Github](https://github.com/dogwantfly/nuxt3-daily-task-live-question/tree/day18-plugin-use)| | 5 | Steven |[Github](https://github.com/y7516552/nuxt3-live-question/tree/day18)| | 6 | MY |[Github](https://github.com/ahmomoz/nuxt3-live-question/tree/day18-plugin-use-hw)| | 7 | Rocky |[Github](https://github.com/WuRocky/Nuxt-Day18-Plugins.git)| | 8 | LinaChen |[Github](https://github.com/Lina-SHU/nuxt3-live-question)| | 9 | Jim Lin |[Github](https://github.com/junhoulin/Nuxt3-hw-day-after10/tree/day18)| | 10 | Johnson |[Github](https://github.com/tttom3669/2024_hex_nuxt_daily/tree/day18-plugin-use)| | 11 | Ariel |[Github](https://github.com/Ariel0508/nuxt3-hw/tree/day18-plugin-use)| | 12 | tanuki狸 |[Github](https://github.com/tanukili/Nuxt-2024-week01-2/tree/day18-plugin-use)| <!-- |---|---|[Github]()| -->
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up