14.

Laravel + Vue.js「Emitted value instead of an instance of Error」の原因と対処

編集
この記事の要点
  • (Emitted value instead of an instance of Error)Vue.js のコンポーネントテンプレートエラー
  • 原因: Vue 2 系の制約「<template> 直下に複数ルート要素」
  • 対処: ルート要素を 1 つだけにする(<div> 等でラップ)
  • Vue 3 ではマルチルート OK: Vue 3 へ移行すれば解消
  • Vue 2 でも functional component や JSX なら複数ルート可

 

エラーの状況

(Emitted value instead of an instance of Error)
  Error compiling template:

    <template>
      <div>...</div>
      <div>...</div>
    </template>

  - Component template should contain exactly one root element.
    If you are using v-if on multiple elements, use v-else-if to chain them instead.

Vue 2 系の制約: 1 つのコンポーネントテンプレートにはルート要素が 1 つだけでなければなりません。

原因と対処

原因 1: 複数のルート要素

<!-- ダメな例 -->
<template>
    <div class="header">ヘッダー</div>
    <div class="body">本文</div>
    <div class="footer">フッター</div>
</template>

<!-- 修正: 1 つの親要素でラップ -->
<template>
    <div class="wrapper">
        <div class="header">ヘッダー</div>
        <div class="body">本文</div>
        <div class="footer">フッター</div>
    </div>
</template>

原因 2: 条件分岐で複数ルート

<!-- ダメな例 -->
<template>
    <div v-if="isLoggedIn">ようこそ</div>
    <div v-else>ログインしてください</div>
</template>

<!-- これは実は OK -->
<!-- v-if と v-else は単一ルートとして扱われる -->

<!-- ダメな例 (条件複数) -->
<template>
    <div v-if="status === 'loading'">読込中</div>
    <div v-if="status === 'success'">完了</div>  <!-- ← v-else-if にすべき -->
    <div v-if="status === 'error'">エラー</div>
</template>

<!-- 修正: v-else-if でチェーン -->
<template>
    <div v-if="status === 'loading'">読込中</div>
    <div v-else-if="status === 'success'">完了</div>
    <div v-else-if="status === 'error'">エラー</div>
</template>

原因 3: コメントが影響することも

<!-- ダメな例 (古い Vue だとコメントも要素扱い) -->
<template>
    <!-- コメント -->
    <div>本体</div>
</template>

<!-- 修正 -->
<template>
    <div>
        <!-- コメント -->
        本体
    </div>
</template>

原因 4: 改行 / テキストノードが混在

<!-- ダメな例 -->
<template>
    テキスト
    <div>div</div>
</template>

<!-- 修正 -->
<template>
    <div>
        テキスト
        <div>div</div>
    </div>
</template>

Vue 3 ではマルチルート可

Vue 3 から「Fragments」が導入され、複数ルート要素 OK になりました:

<!-- Vue 3 ではこれが OK -->
<template>
    <header>ヘッダー</header>
    <main>本文</main>
    <footer>フッター</footer>
</template>

属性の継承注意

<!-- 親から渡される属性は明示的に -->
<template>
    <header v-bind="$attrs">ヘッダー</header>  <!-- どこに属性を付けるか明示 -->
    <main>本文</main>
</template>

<script setup>
defineOptions({
    inheritAttrs: false  // 暗黙の継承を無効化
});
</script>

Vue 2 で複数ルートを扱う方法

① Functional Component

<!-- Vue 2 の functional component -->
<template functional>
    <div>
        <slot />
        <slot name="footer" />
    </div>
</template>

<!-- render 関数で複数子要素を返す -->
<script>
export default {
    functional: true,
    render(h, context) {
        return [
            h("header", "ヘッダー"),
            h("main", context.slots().default),
            h("footer", "フッター")
        ];
    }
};
</script>

② JSX で複数ルート (Babel + jsx プラグイン)

export default {
    render() {
        return [
            <header>ヘッダー</header>,
            <main>本文</main>,
            <footer>フッター</footer>
        ];
    }
};

③ <template> タグ複数(v-for / v-if のみ)

<!-- v-for を template で囲める(要素を出力しない) -->
<template>
    <ul>
        <template v-for="item in items" :key="item.id">
            <li>{{ item.name }}</li>
            <li class="meta">{{ item.meta }}</li>
        </template>
    </ul>
</template>

関連エラー

エラー意味
Component template should contain exactly one root element同じエラー(このページ)
v-if/v-else-if/v-else used on different elementsv-if/v-else が別要素にある
Multiple root nodes returned from render functionrender() が配列を返すが Vue 2
Failed to mount component: template or render function not definedtemplate も render() もない
Cannot read property of undefined (in template)data 未定義 or 非同期未完了でアクセス

Vue 2 → 3 移行のメリット

  • Fragments: 複数ルート可、不要な wrapper div 削減
  • Composition API: ロジック再利用がより柔軟
  • パフォーマンス向上: 仮想 DOM の最適化
  • TypeScript サポート強化
  • Vite 連携: ビルド高速化
  • Vue 2 は 2024-01 EOL: セキュリティパッチも終了、移行推奨

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost'
  2. Add [~] to fillable property to allow mass assignment on [App\~].
  3. PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or variable (T_VARIABLE) or '{' or '$' in ~
  4. Changing columns for table "~" requires Doctrine DBAL; install "doctrine/dbal"
  5. MethodNotAllowedHttpException No message
  6. Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found
  7. production.ERROR: No application encryption key has been specified.
  8. Dotenv values containing spaces must be surrounded by quotes.
  9. Laravel \ Socialite \ Two \ InvalidStateException
  10. The page has expired due to inactivity. Please refresh and try again.
  11. Failed to clone https://github.com/symfony/thanks.git via https, ssh protocol
  12. Illegal offset type
  13. Cannot access protected property Illuminate\Http\Request::$...
  14. Emitted value instead of an instance of Error
  15. 画像保存時にInternal Server Error
  16. Failed to authenticate on SMTP server with username ...
  17. PostTooLargeException
  18. Database hosts array is empty.
  19. Invalid request (Unsupported SSL request)
  20. does not comply with psr-4 autoloading standard. Skipping.
  21. MySQLのSTR_TO_DATE関数を使用するとnullが返却される問題

最近更新/作成されたページ