Vue warn: ‘$listeners is readonly’ when using Composition APIの解決方法
「Vue warn: ‘$listeners is readonly’ when using Composition API」エラーは、Vue 3におけるComposition APIの使用時に発生する特定の状況に関連しています。このエラーの原因と解決方法について詳しく説明します。
エラーの発生条件
- Vue 3でComposition APIを使用している場合
- プロパティの$listenersにアクセスしようとした場合
- 古いVue 2のコードが混在している場合
エラー例
以下は、Composition APIで$listenersに直接アクセスした場合の例です。
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup(props, { listeners }) {
console.log(listeners); // エラー発生
}
});
</script>上記のコードで、$listenersプロパティが読み取り専用であるためエラーが発生します。
エラーの背景
- $listenersはVue 2に存在していたプロパティで、親コンポーネントから子コンポーネントに渡されたイベントリスナーを表していました。
- Vue 3では、この機能が削除され、イベントリスナーはsetup関数の引数で提供されるcontext(デストラクチャリングで取得可能)を通じて取得されます。
解決方法: context.attrsを使用する
Vue 3では、$listenersはcontext.attrsに統合されています。代わりに以下のように記述します。
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup(props, { attrs }) {
console.log(attrs); // イベントリスナーも含むすべての属性が表示される
}
});
</script>解決方法: emitを使用してイベントを処理する
Vue 3では、親から渡されるイベントを処理するために`emit`を使用します。
<script>
import { defineComponent } from 'vue';
export default defineComponent({
props: ['message'],
emits: ['update'],
setup(props, { emit }) {
const updateMessage = () => {
emit('update', '新しいメッセージ');
};
return { updateMessage };
}
});
</script>原因の例: Vue 2からVue 3への移行時のコード
Vue 2でのコードがそのままVue 3に移行された場合、$listenersや$attrsが誤って使用されていることがあります。以下は移行時の問題の例です。
// Vue 2
export default {
render(h) {
return h('button', { on: this.$listeners }, 'クリック');
}
};
// Vue 3移行後の修正例
import { defineComponent } from 'vue';
export default defineComponent({
setup(props, { attrs }) {
return () => <button {...attrs}>クリック</button>;
}
});解決方法: Composition APIの標準的な使用
Composition APIでは、contextから必要な属性やイベントを明示的に取得します。
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup(props, { attrs }) {
return () => <div {...attrs}>属性がここに渡されます</div>;
}
});
</script>解決方法: Vue CLIやViteでの構成確認
プロジェクトのビルドツールがVue 3を正しくサポートしているか確認します。Vue 3での$listenersはサポートされていないため、ライブラリやプラグインが対応しているか確認してください。
テンプレート内での属性バインディング
テンプレート内では、$attrsを使用してすべての未解決の属性をバインディングできます。
<template>
<div v-bind="attrs">コンテンツ</div>
</template>
<script>
export default {
inheritAttrs: false,
setup(props, { attrs }) {
return { attrs };
}
};
</script>まとめ
「Vue warn: ‘$listeners is readonly’ when using Composition API」は、Vue 2からVue 3への変更点に関連するエラーです。Vue 3では$listenersが削除され、代わりにcontext.attrsやemitを利用する設計になっています。移行時のコードの見直しや、Composition APIの標準的な使い方に従うことで、このエラーを解決できます。
-
前の記事
Error: This socket is closed の解決方法 2025.08.06
-
次の記事
Vue warn: Avoid using .native modifier with non-component elementsの解決方法 2025.08.07
コメントを書く