子组件发出的Vue.js事件未到达父组件

时间:2020-04-24 08:11:47

标签: vue.js events

在我的vue.js应用程序中,我有一个内部带有子组件的组件,这些子组件属于组件类型“ Test”或“ AnotherComponent”。 用户可以通过单击按钮添加这些组件之一,然后将其添加到子组件列表的末尾。

每个组件都应具有一个删除按钮,以从显示的列表中删除该组件。

我在“ AnotherComponent”中添加了这样的按钮,并且在单击时添加了事件发射器,因为我想将事件通知给父组件,因此它将负责从列表中删除正确的组件。这种方法完全正确吗?

这是子组件

<template>
  <div>
    <div class="container">
        <b-card
            title="Card Title"
            class="mb-2"
        >
            <b-card-text>
                This card has some text and it different from the other component.
                Also there is a nice picture.
            </b-card-text>
            <button
                type="button"
                class="btn btn-secondary"
                v-on:click="deleteComponent()"
            >
              x
            </button>
        </b-card>
  </div>
  </div>
</template>

<script>

export default {
  name: 'AnotherComponent',
  data() {
    return {
    };
  },
  methods: {
    deleteComponent(event) {
      this.$emit('delete-component', this.$vnode.key);
    },
  },
};
</script>

这是父组件:

<template>
  <div>
    <div class="container">
      <h1> This is my first layout page </h1>
      <alert :message=alertText></alert>
      <button
        type="button"
        class="btn btn-primary"
        v-on:click="addComponent('test')"
      >
        add component 1
      </button>
      <button
        type="button"
        class="btn btn-primary"
        v-on:click="addComponent('another')"
      >
        add component 2
      </button>
      <div class="row">
        <template
          v-for="block in content.body">
            <div class="col-3" v-bind:key="`col-${block._uid}`">
              <component
                :is="block.component"
                :block="block"
                :key="block._uid"
                v-on:delete-component="onDeleteChildComponent($event)">
              </component>
            </div>
        </template>
      </div>
  </div>
  </div>
</template>

<script>
/* eslint-disable vue/no-unused-components */
import axios from 'axios';

import TestComponent from './TestComponent.vue';
import AnotherComponent from './AnotherComponent.vue';
import Alert from './Alert.vue';

export default {
  name: 'FirstPage',
  data() {
    return {
      alertText: 'this is a test!',
      content: {
        body: [], /* holds the array of objects that are components */
      },
    };
  },
  components: {
    alert: Alert,
    test: TestComponent,
    another: AnotherComponent,
    // AnotherComponent,
  },
  methods: {
    getComponents() {
      const path = 'http://localhost:8080/components';
      axios.get(path)
        .then((res) => {
          console.log('res.data');
          this.content.body = res.data.components;
        })
        .catch((error) => {
          // eslint-disable-next-line
          console.error(error);
        });
    },
    addComponent(componentType) {
      const path = 'http://localhost:8080/components';
      const payload = {
        component: componentType,
        headline: 'Bar',
      };
      axios.post(path, payload)
        .then(() => {
          this.getComponents();
          this.message = 'Component added!';
        })
        .catch((error) => {
          // eslint-disable-next-line
          console.log(error);
          this.getComponents();
        });
    },
  },
  onDeleteChildComponent(id) {
    console.log('delete child');
    console.log(id);
  },
  created() {
    console.log('fetching components from backend');
    this.getComponents();
  },
};
</script>

不幸的是,在父组件中,这个子事件根本没有被触发。 我只是从vue.js开始,所以我在这里做错了什么?提前致谢!

1 个答案:

答案 0 :(得分:1)

您正在发出'deleteComponent'并在听'delete-component'。此转换不适用于事件注册,仅用于转换组件名称。

https://vuejs.org/v2/guide/components-custom-events.html

尝试以下方法:

// child component

methods: {
    deleteComponent(event) {
      this.$emit('delete-component', this.$vnode.key);
    },
  },

编辑:正如Eldar在评论中正确指出的那样,您的听众也在听错误的元素。将侦听器移至动态组件,如下所示:

// parent component

<!-- template tags not necessary unless you're trying to render more than 1 root node per v-for element -->

            <div class="col-3" v-for="block in content.body" :key="`col-${block._uid}`">
              <component
                @delete-component="onDeleteChildComponent($event)"
                :is="block.component"
                :block="block"
                :key="block._uid">
              </component>
            </div>

编辑2:您尝试收听的方法未在您的方法中列出,但级别太高。跟踪您的括号! ;)

methods: {
    getComponents() {
      ...
    },
    addComponent(componentType) {
      ...
    },
  },
  onDeleteChildComponent(id) {
    console.log('delete child');
    console.log(id);
  },

应为:

methods: {
    getComponents() {
      ...
    },
    addComponent(componentType) {
      ...
    },
    onDeleteChildComponent(id) {
      console.log('delete child');
      console.log(id);
    },
  },