ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|---|
|
エラーの状況
(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>
];
}
};
③ タグ複数(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: セキュリティパッチも終了、移行推奨
関連記事
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
同階層のページ
- 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 Spring Frameworkのアノテーション一覧
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- PHPでのファイルアップロード方法|multipart/form-dataと$_FILES 2026-08-07 17:15:57
- PHP $_SERVERとは|DOCUMENT_ROOT・PHP_SELFなど主な要素 2026-08-07 17:15:57
- Scratchのアカウントの作り方|メールアドレスとユーザー名の登録手順 2026-08-07 17:15:57
- djangoにおけるMVCアプリケーション実装例 2026-08-07 17:15:57
- Bluetoothとは|仕組み・BLEとClassicの違い・用途 2026-08-07 17:15:57
- Spring Bootのテスト入門|@SpringBootTestとJUnitでの単体・結合テスト 2026-08-07 17:15:57
- APIキー取得方法 2026-08-07 17:15:56
- インストール方法(Windows版) 2026-08-07 17:15:56
- Java とは?言語仕様・JVM・主要フレームワーク一覧 2026-08-07 17:15:56
- 【PHPフレームワーク】Laravelの使い方 2026-08-07 17:15:56
- Scratch 作品の公開方法 2026-08-07 17:15:56
- Google OAuth 2.0 認証の実装方法 2026-08-07 17:15:56
- データベースとは?RDB / NoSQL / SQL の基礎 2026-08-07 17:15:56
- インストール(eclipseプラグイン) 2026-08-07 17:15:56
- Spring Frameworkの使い方 2026-08-07 17:15:56
コメントを削除してもよろしいでしょうか?