Vue で「Failed to resolve component」が解決できない
`[Vue warn]: Failed to resolve component` は、テンプレートで使ったコンポーネントが登録されていないときに出る。
`<script setup>` では import するだけでローカル登録され、Options API では components への登録、全体で使うならグローバル登録が必要。
#vue#component#registration#script-setup#composition-api
公開:
要約
[Vue warn]: Failed to resolve component: MyButton は、テンプレートに書いたコンポーネントを Vue が見つけられないときの警告です。
原因はほぼ「登録漏れ」か「名前のずれ」。<script setup> を使っていれば import するだけで自動的にローカル登録されるので、まずはそこを確認します。
よくある原因
- components への登録漏れ:
<script setup>を使わない Options API では、import しただけでは使えずcomponentsへの登録が必要。 - 名前のずれ:
<MyButton />と書いたのに登録名がMybuttonになっている、などのタイポ。
Vue は PascalCase と kebab-case を相互に解決しますが、綴り自体が違うと解決できません。 - グローバル登録の順序:
app.component()をコンポーネント使用後やマウント後に呼んでいる。 - 動的コンポーネント:
<component :is="name">のnameに未登録の文字列を渡している。
解決策
1. <script setup> なら import だけでよい
<script setup>
import MyButton from './MyButton.vue'
</script>
<template>
<MyButton />
</template>コンポーネントの登録 のとおり、<script setup> 内で import したコンポーネントは自動でローカル登録されます。
2. Options API は components に登録する
<script>
import MyButton from './MyButton.vue'
export default {
components: { MyButton },
}
</script>3. 全体で使うならグローバル登録
import { createApp } from 'vue'
import App from './App.vue'
import MyButton from './components/MyButton.vue'
const app = createApp(App)
app.component('MyButton', MyButton) // mount より前に登録
app.mount('#app')グローバル登録は便利な一方、未使用でもビルドに含まれ tree-shaking されにくいので、使う箇所が限られるならローカル登録を優先します。
4. 動的コンポーネントは定義を渡す
<script setup>
import Foo from './Foo.vue'
import { shallowRef } from 'vue'
const current = shallowRef(Foo) // 文字列 'Foo' ではなく定義を渡す
</script>
<template>
<component :is="current" />
</template>文字列名で切り替えたい場合は、名前からコンポーネントへのマップを自前で用意するか、対象をグローバル登録しておきます。