できない.dev

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 するだけで自動的にローカル登録されるので、まずはそこを確認します。

よくある原因

  1. components への登録漏れ: <script setup> を使わない Options API では、import しただけでは使えず components への登録が必要。
  2. 名前のずれ: <MyButton /> と書いたのに登録名が Mybutton になっている、などのタイポ。
    Vue は PascalCase と kebab-case を相互に解決しますが、綴り自体が違うと解決できません。
  3. グローバル登録の順序: app.component() をコンポーネント使用後やマウント後に呼んでいる。
  4. 動的コンポーネント: <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>

文字列名で切り替えたい場合は、名前からコンポーネントへのマップを自前で用意するか、対象をグローバル登録しておきます。

この記事は役立ちましたか?