javascript 子组件发出Vue 3中未要求的事件

uinbv5nw  于 2023-01-11  发布在  Java
关注(0)|答案(1)|浏览(138)

我正在将我的中型应用程序从Vue2迁移到Vue3。我注意到Vue3的子-父发射机制与Vue2不同,这让我很困惑。
下面是一个基本示例

// App.vue
<script>
import InputWrap from './InputWrap.vue';
export default {
  name: 'App',
  components: {
    InputWrap,
  },
  data() {
    return {
      msg: 'Hello world',
    }
  },
  methods: {
    onChange() {
      console.log('why change?');
    }
  }
}
</script>

<template>
  <h1>{{ msg }}</h1>
  <input-wrap v-model="msg" @change="onChange" />
</template>
// InputWrap.vue
<script>
  import MyInput from './MyInput.vue';
  export default {
    name: 'InputWrap',
    components: {
      MyInput,
    },
    props: ['modelValue'],
    methods: {
      onUpdate(v) {
        this.$emit('update:modelValue', v);
      }
    }
  }
</script>

<template>
  <my-input :modelValue="modelValue" @update:modelValue="onUpdate" />
</template>
// MyInput.vue
<script>
export default {
  name: 'MyInput',
  props: {
    modelValue: String,
  },
  methods: {
    onInput(e) {
      this.$emit('update:modelValue', e.target.value);
    }
  }
}
</script>

<template>
<input :value="modelValue" @input="onInput" />
</template>

连接到Vue SFCPlayground。
我很好奇为什么onChange事件处理程序在App.vue中被调用?
看起来change事件是由MyInput.vue中的input元素生成的。但是为什么这个事件会通过所有组件并在App.vue中被捕获,这一点完全不透明。想象一下,一棵树有几十个嵌套的组件,一个根组件在侦听change事件。这完全是一团糟。
Vue2有一个不同的方法,我喜欢它,因为它有一个透明的子-父通信。有可能打开Vue2发射机制在Vue3?

l0oc07j2

l0oc07j21#

原因是Vue实现了故障属性机制
“fallthrough属性”是传递给组件的属性或v-on事件侦听器,但未在接收组件的props或emits中显式声明。
当组件呈现单个根元素时,fallthrough属性将自动添加到根元素的属性
在示例中,零部件满足两个条件:

  • InputWrap.vue渲染单个根元素(MyInput.vue组件)
  • InputWrap.vue不将onChange声明为组件的发射

MyInput.vue组件相同
因此@change侦听器将无法到达input元素。
要禁用fallthrough属性,您可以将属性声明为子组件的props/emits,或者通过添加inheritAttrs: false禁用该组件的整个功能:

// InputWrap.vue
<script>
  import MyInput from './MyInput.vue';
  export default {
    name: 'InputWrap',
    components: {
      MyInput,
    },
    inheritAttrs: false   
  }
</script>

SFC链路
Vue 2仅继承属性

相关问题