在 Vue 開發中,使用自訂元件前必須先「註冊」該元件,否則 Vue 不知道這個標籤對應到哪個元件,就不會渲染出來。這是新手常見的問題之一。
問題描述
在 Options API 中,如果直接在 template 使用元件而沒有在 components 選項中宣告,該元件就不會出現,也不會有明顯的錯誤(只是靜默地不渲染),Vue DevTools 或 Console 可能會顯示類似以下的警告:
1
2
|
[Vue warn]: Failed to resolve component: MyComponent
If this is a native custom element, make sure to exclude it from component resolution...
|
Vue 2:Options API 的元件註冊
局部註冊(推薦)
1
2
3
4
5
6
7
8
9
10
|
import Header from './components/Header.vue'
import MyAnimeList from './components/MyAnimeList.vue'
export default {
components: {
Header,
MyAnimeList
},
// ...
}
|
在 components 中宣告後,就可以在 template 中使用:
1
2
3
4
5
6
|
<template>
<div>
<Header />
<MyAnimeList />
</div>
</template>
|
全局註冊
全局註冊後,所有元件都不需要重複宣告:
1
2
3
4
5
|
// main.js
import Vue from 'vue'
import Header from './components/Header.vue'
Vue.component('Header', Header) // 全局註冊
|
全局註冊的缺點是:即使某個頁面用不到,這個元件仍然會被打包進去,增加 bundle 大小。
Vue 3:Composition API 與 <script setup>
Options API(同 Vue 2 寫法)
1
2
3
4
5
6
7
8
9
10
11
|
import { defineComponent } from 'vue'
import Header from './components/Header.vue'
export default defineComponent({
components: {
Header
},
setup() {
// ...
}
})
|
<script setup>(最推薦的寫法)
使用 <script setup> 時,import 進來的元件會自動註冊,不需要手動在 components 中宣告,這也是為什麼有些人用 setup 寫法反而沒問題的原因:
1
2
3
4
5
6
7
8
9
10
|
<script setup>
import Header from './components/Header.vue'
import MyAnimeList from './components/MyAnimeList.vue'
// import 就等於自動註冊,可直接在 template 使用
</script>
<template>
<Header />
<MyAnimeList />
</template>
|
全局註冊(Vue 3)
1
2
3
4
5
6
7
8
|
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import Header from './components/Header.vue'
const app = createApp(App)
app.component('Header', Header) // 全局註冊
app.mount('#app')
|
局部 vs 全局註冊的選擇
|
局部註冊 |
全局註冊 |
| Tree-shaking |
✅ 支援(未使用不打包) |
❌ 不支援 |
| 使用便利性 |
每個元件都要 import |
一次設定到處使用 |
| 適合場景 |
一般頁面元件 |
全站共用的基礎元件(Button、Icon 等) |
參考資料