この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: Emitted value instead of an instance of Error
SEOタイトル: 【Vue.jsエラー】Emitted value instead of an instance of Error

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="1" cellspacing="1" style="width:1000px">
	<thead><tr><th style="background-color:#f39c12;color:#ffffff;text-align:left">この記事の要点</th></tr></thead>
	<tbody><tr><td style="background-color:#fef9e7"><ul>
				<li><code>(Emitted value instead of an instance of Error)</code> は<strong>Vue.js のコンポーネントテンプレートエラー</strong></li>
				<li>原因: Vue 2 系の制約「<code><template></code> 直下に複数ルート要素」</li>
				<li>対処: ルート要素を 1 つだけにする(<code><div></code> 等でラップ)</li>
				<li><strong>Vue 3 ではマルチルート OK</strong>: Vue 3 へ移行すれば解消</li>
				<li>Vue 2 でも <code>functional component</code> や JSX なら複数ルート可</li>
			</ul></td></tr></tbody>
</table>

<p>&nbsp;</p>

<h2>エラーの状況</h2>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code>(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.</code></pre>


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

<h2>原因と対処</h2>

<h3>原因 1: 複数のルート要素</h3>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code><!-- ダメな例 -->
<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></code></pre>


<h3>原因 2: 条件分岐で複数ルート</h3>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code><!-- ダメな例 -->
<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></code></pre>


<h3>原因 3: コメントが影響することも</h3>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code><!-- ダメな例 (古い Vue だとコメントも要素扱い) -->
<template>
    <!-- コメント -->
    <div>本体</div>
</template>

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


<h3>原因 4: 改行 / テキストノードが混在</h3>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code><!-- ダメな例 -->
<template>
    テキスト
    <div>div</div>
</template>

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


<h2>Vue 3 ではマルチルート可</h2>

<p>Vue 3 から「Fragments」が導入され、複数ルート要素 OK になりました:</p>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code><!-- Vue 3 ではこれが OK -->
<template>
    <header>ヘッダー</header>
    <main>本文</main>
    <footer>フッター</footer>
</template></code></pre>


<h3>属性の継承注意</h3>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code><!-- 親から渡される属性は明示的に -->
<template>
    <header v-bind="$attrs">ヘッダー</header>  <!-- どこに属性を付けるか明示 -->
    <main>本文</main>
</template>

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


<h2>Vue 2 で複数ルートを扱う方法</h2>

<h3>① Functional Component</h3>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code><!-- 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></code></pre>


<h3>② JSX で複数ルート (Babel + jsx プラグイン)</h3>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code>export default {
    render() {
        return [
            <header>ヘッダー</header>,
            <main>本文</main>,
            <footer>フッター</footer>
        ];
    }
};</code></pre>


<h3>③ <template> タグ複数(v-for / v-if のみ)</h3>
<pre style="background:#0f172a;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;font-family:Consolas,Monaco,monospace;font-size:0.9em;line-height:1.5"><code><!-- 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></code></pre>


<h2>関連エラー</h2>

<table border="1" cellpadding="1" cellspacing="1" style="width:1000px">
	<thead><tr><th>エラー</th><th>意味</th></tr></thead>
	<tbody>
		<tr><td>Component template should contain exactly one root element</td><td>同じエラー(このページ)</td></tr>
		<tr><td>v-if/v-else-if/v-else used on different elements</td><td>v-if/v-else が別要素にある</td></tr>
		<tr><td>Multiple root nodes returned from render function</td><td>render() が配列を返すが Vue 2</td></tr>
		<tr><td>Failed to mount component: template or render function not defined</td><td>template も render() もない</td></tr>
		<tr><td>Cannot read property of undefined (in template)</td><td>data 未定義 or 非同期未完了でアクセス</td></tr>
	</tbody>
</table>

<h2>Vue 2 → 3 移行のメリット</h2>

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

<h2>関連記事</h2>

<ul>
	<li><a href="/article/21291">ライフサイクルフック</a></li>
	<li><a href="/article/21292">$nextTick の使い方</a></li>
</ul>