---
# System prepended metadata

title: "\U0001F3C5 Day 18"
tags: [2024 Nuxt 直播班]

---

# 🏅 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` 的錯誤。

![day18-1](https://hackmd.io/_uploads/ryQy7TaM1e.png)



### 步驟三. 在模板中使用元件

在 `/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 則正常。
![day18-2](https://hackmd.io/_uploads/H1kg7pTzkg.png)

<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://i.imgur.com/vftL5i0.png)

<!--   

解答 :  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]()|
 -->