44
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue 3から素のemitが警告されるようになったので対処する

Last updated at Posted at 2020-07-05

再現方法

親子関係のcomponentsにおいて、子から親にemitすること

警告の内容

[Vue warn]: Extraneous non-emits event listeners (rewrite) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. If the listener is intended to be a component custom event listener only, declare it using the "emits" option. at ...

コンポーネントがフラグメントまたはテキストのルートノードをレンダリングするため、外部の非エミッツイベントリスナー(書き換え)がコンポーネントに渡されましたが、自動的に継承することができませんでした。
リスナーがコンポーネントのカスタムイベントリスナーのみを意図している場合は、"emits "オプションを使用して宣言してください。
[翻訳] DeepL

結論

子(emitする側)のコンポーネントでemitsオプションを定義した上で、emit名を配列で宣言する。
以下のESLintルールに詳しい。
https://eslint.vuejs.org/rules/require-explicit-emits.html
このルールが追加された背景としてはコンポーネントからどんなイベントがemitされるのかを構造的に宣言できるようにすることでコードの自己文書化をしよう!みたいな意図だと理解した。

詳細なコード

親で定義したmsg変数を子のinputタグで書き換える単純なprops down, emits upの構成

親コンポーネント

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld :msg="msg" @rewrite="changeMsg" />
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'

export default defineComponent({
  name: 'App',
  components: {
    HelloWorld,
  },
  setup() {
    let msg = ref('Hello Vue 3.0 + Vite')
    const changeMsg = (e) => {
      msg.value = e.target.value
    }
    return {
      msg,
      changeMsg,
    }
  },
})
</script>

子コンポーネント

<template>
  <h1>{{ msg }}</h1>
  <button @click="count++">count is: {{ count }}</button>
  <p>
    Edit <code>components/HelloWorld.vue</code> to test hot module replacement.
  </p>
  <input type="text" :value="msg" @input="changeMsg" />
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
type Props = {
  msg: string
}
export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: {
      type: String,
      default: 'default Value',
    },
  },
  emits: ['rewrite'], // このオプションが必要
  setup(props: Props, { emit }) {
    const count = ref(0)
    const changeMsg = (e) => {
      emit('rewrite', e)
    }
    return {
      count,
      changeMsg,
    }
  },
})
</script>

何が詰まったか

  1. emitsオプションを定義すべきことは分かるが、どういった形式で宣言すべきか、また何を宣言すべきかのヒントが無い
  2. 警告内容でググっても現時点ではこのルールそのもののPRしかヒットせず、どうすれば解決するかが掴めない(https://github.com/vuejs/vue-next/issues/1001)
  3. 純粋にググラビリティが低く、vue 3 emits option等検索しても2.x時代のドキュメントが大量にヒットしてしまう

というわけで

謎に詰まってしまった。。。
おもむろに親子間でemitするだけで警告されるので、2.x時代からVueを書いている方はお気をつけください。

44
14
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?