当事件从动态组件 child 发出时,Vue `vm.$on()` 回调在 parent 中不起作用

Vue `vm.$on()` callback not working in parent when event is emitted from dynamic component child

我遇到一个问题,动态组件(A.vueB.vue)发出的自定义事件(swap-components)在 parent 的动态组件 (HelloWorld.vue).

这里是 source on GitHub(使用 vue cli 3 创建)。

这里是live demo showing the problem.

在现场演示中,您会看到单击具有背景色的动态组件中的按钮不会更改动态组件。但是当单击背景颜色下方的按钮时(源自 HelloWorld.vue parent),动态组件确实发生了变化。

为什么会发生这种情况以及如何解决?


下面我将把感兴趣的 3 个主要文件的内容复制到这个 post:

  1. HelloWorld.vue (parent)

  2. A.vue(动态组件中使用的子组件)

  3. B.vue(动态组件中使用的子组件)

HelloWorld.vue:

<template>
  <div>
    <h1>The dynamic components ⤵️</h1>
    <component
      :is="current"
      v-bind="dynamicProps"
    ></component>
    <button
      @click="click"
    >Click me to swap components from within the parent of the dynamic component</button>
  </div>
</template>

<script>
import A from "./A.vue";
import B from "./B.vue";

export default {
  data() {
    return {
      current: "A"
    };
  },
  computed: {
    dynamicProps() {
      return this.current === "A" ? { data: 11 } : { color: "black" };
    }
  },
  methods: {
    click() {
      this.$emit("swap-components");
    },
    swapComponents() {
      this.current = this.current === "A" ? "B" : "A";
    }
  },
  mounted() {
    this.$nextTick(() => {
      // Code that will run only after the
      // entire view has been rendered
      this.$on("swap-components", this.swapComponents);
    });
  },
  components: {
    A,
    B
  },
  props: {
    msg: String
  }
};
</script>

A.vue:

<template>
  <section id="A">
    <h1>Component A</h1>
    <p>Data prop sent from parent: "{{ data }}"</p>
    <button @click="click">Click me to swap components from within the dynamic component</button>
  </section>
</template>

<script>
export default {
  props: ["data"],
  methods: {
    click() {
      this.$emit("swap-components");
    }
  }
};
</script>

B.vue:

<template>
  <section id="B">
    <h1>Component B</h1>
    <p>Color prop sent from parent: "{{ color }}"</p>
    <button @click="click">Click me to swap components from within the dynamic component</button>
  </section>
</template>

<script>
export default {
  props: ["color"],
  methods: {
    click() {
      this.$emit("swap-components");
    }
  }
};
</script>
当您使用函数时,

this 不再绑定到上下文。仅限于功能范围。使用箭头函数让this绑定到父上下文。

变化:

this.$nextTick(function() {

与:

this.$nextTick(() => {

我猜这是因为事件侦听器正在侦听父组件本身发出的 swap-components 事件。也许您可以通过从子组件侦听 swap-components 事件然后在父组件上发出事件来解决此问题。

<template>
  <div>
    <h1>The dynamic components ⤵️</h1>
    <component
      :is="current"
      v-bind="dynamicProps"
      @swap-components="$emit('swap-components')"
    ></component>
    <button
      @click="click"
    >Click me to swap components from within the parent of the dynamic component</button>
  </div>
</template>

或者你可以在子组件发出事件时直接调用你的方法..

<template>
      <div>
        <h1>The dynamic components ⤵️</h1>
        <component
          :is="current"
          v-bind="dynamicProps"
          @swap-components="swapComponents"
        ></component>
        <button
          @click="click"
        >Click me to swap components from within the parent of the dynamic component</button>
      </div>
    </template>