| この記事の要点 |
|---|
|
エラーの状況
(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 elements | v-if/v-else が別要素にある |
| Multiple root nodes returned from render function | render() が配列を返すが Vue 2 |
| Failed to mount component: template or render function not defined | template も 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: セキュリティパッチも終了、移行推奨
関連記事
- ライフサイクルフック
- $nextTick の使い方
- vue.jsとの連携 — Laravel 側の組み込み方
- Vue.jsと連携するSPA実行環境構築
- エラー一覧 — Laravel の他のエラー
子ページ
子ページはありません
同階層のページ
- SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost'
- Add [~] to fillable property to allow mass assignment on [App\~].
- PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or variable (T_VARIABLE) or '{' or '$' in ~
- Changing columns for table "~" requires Doctrine DBAL; install "doctrine/dbal"
- MethodNotAllowedHttpException No message
- Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found
- production.ERROR: No application encryption key has been specified.
- Dotenv values containing spaces must be surrounded by quotes.
- Laravel \ Socialite \ Two \ InvalidStateException
- The page has expired due to inactivity. Please refresh and try again.
- Failed to clone https://github.com/symfony/thanks.git via https, ssh protocol
- Illegal offset type
- Cannot access protected property Illuminate\Http\Request::$...
- Emitted value instead of an instance of Error
- 画像保存時にInternal Server Error
- Failed to authenticate on SMTP server with username ...
- PostTooLargeException
- Database hosts array is empty.
- Invalid request (Unsupported SSL request)
- does not comply with psr-4 autoloading standard. Skipping.
- MySQLのSTR_TO_DATE関数を使用するとnullが返却される問題
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- プロジェクトをTomcatプロジェクトとして認識させる方法 2026-10-07 22:32:50
- MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー 2026-10-07 21:54:03
- curlの証明書ホスト名不一致|旧エラー51・現行60の確認と対処 2026-10-07 21:54:03
- LaravelのMassAssignmentException|fillableの原因と安全な対処 2026-10-07 21:54:03
- Eclipse で Tomcat の起動ログがコンソールに出ない時の確認手順 2026-10-07 21:54:02
- MySQLにおける中央値(Median)の導き方(バージョン8未満) 2026-10-07 13:49:45
- getInputForward 2026-10-07 13:41:15
- JSONから配列に変換 2026-10-07 13:41:15
- ビューから値をモデルに格納しコントローラーで受け取る方法 2026-10-07 13:23:41
- Laravelのテーブル作成と定義変更|マイグレーション・up/down・注意点 2026-10-07 13:23:41
- NumPy 配列に要素を追加する方法 (append / concatenate) 2026-10-07 13:23:41
- MariaDB・MySQLで現在日時を取得する方法|NOW・タイムゾーン・保存型 2026-10-07 13:13:36
- 【django】テンプレートで定数を使用する方法 2026-10-07 13:10:15
- Spring BootにおけるApplication.propertiesの環境依存設定の分割方法 2026-10-07 12:09:35
- Not supported for DML operations【Springエラー】 2026-10-07 11:09:38