【问题标题】:Vue `vm.$on()` callback not working in parent when event is emitted from dynamic component child当从动态组件子组件发出事件时,Vue `vm.$on()` 回调在父组件中不起作用
【发布时间】:2019-05-26 17:48:40
【问题描述】:

我遇到了一个问题,即从动态组件(A.vueB.vue)发出的自定义事件 (swap-components) 在动态组件的父级 (HelloWorld.vue) 中没有被正确监听.

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

这是live demo showing the problem

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

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


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

  1. HelloWorld.vue(父)

  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>

【问题讨论】:

    标签: vue.js vue-dynamic-components


    【解决方案1】:

    我猜这是因为事件侦听器正在侦听父组件本身发出的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>
    

    【讨论】:

      【解决方案2】:

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

      变化:

      this.$nextTick(function() {
      

      与:

      this.$nextTick(() => {
      

      【讨论】:

      • 箭头 fn 仍然不起作用 - 我更新了上面的代码和现场演示。
      • 子组件发出的事件应该可以正常工作。我看到您在父组件上使用 emit 的问题。你可能想用上?这个post 可以帮助你。
      猜你喜欢
      • 2021-07-26
      • 2018-09-30
      • 2020-12-09
      • 2019-08-10
      • 2018-05-04
      • 2018-10-24
      • 2021-02-03
      • 2021-02-12
      • 2019-11-03
      相关资源
      最近更新 更多