使用动态组件和自定义事件时的 VueJS 警告

VueJS warning when using dynamic components and custom-events

因此,我收到此警告:

" Extraneous non-emits event listeners (addNewResource) 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."

我不明白为什么。我正在使用带有 2 个自定义事件的动态组件。我已经尝试将两个发出的事件添加到两个组件的 emits 对象中。

App.vue

<template>
  <AppHeader />
  <NavigationBar @select-component="selectComponent" />
  <keep-alive>
    <component
      :is="selectedComponent"
      v-bind="componentProps"
      @delete-resource="deleteResource"
      @add-new-resource="addNewResource"
    ></component>
  </keep-alive>
</template>

<script>
import AppHeader from "./components/SingleFile/AppHeader.vue";
import NavigationBar from "./components/NavigationBar.vue";
import LearningResources from "./components/LearningResources.vue";
import AddResource from "./components/AddResource.vue";

export default {
  components: {
    AppHeader,
    NavigationBar,
    LearningResources,
    AddResource,
  },
  data() {
    return {
      selectedComponent: "learning-resources",
      learningResources: [
        {
          name: "Official Guide",
          description: "The official Vue.js documentation",
          link: "https://v3.vuejs.org",
        },
        {
          name: "Google",
          description: "Learn to google...",
          link: "https://www.google.com/",
        },
      ],
    };
  },
  methods: {
    selectComponent(component) {
      this.selectedComponent = component;
    },
    deleteResource(name) {
      this.learningResources = this.learningResources.filter(
        (resource) => resource.name !== name
      );
    },
    addNewResource(newResourceObject) {
      const newResource = {
        name: newResourceObject.title,
        description: newResourceObject.description,
        link: newResourceObject.link,
      };
      this.learningResources.push(newResource);
    },
  },
  computed: {
    componentProps() {
      if (this.selectedComponent === "learning-resources") {
        return {
          learningResources: this.learningResources,
        };
      }
      return null;
    },
  },
};
</script>

AddResource.vue

<template>
  <base-card>
    <template #default>
      <form @submit.prevent>
        <div>
          <label for="title">Title</label>
          <input type="text" v-model="newResource.title" />
        </div>
        <br />

        <div>
          <label for="description">Description</label>
          <textarea rows="3" v-model="newResource.description" />
        </div>
        <br />

        <div>
          <label for="link">Link</label>
          <input type="text" v-model="newResource.link" />
        </div>

        <button @click="$emit('add-new-resource', newResource)">
          Add Resource
        </button>
      </form>
    </template>
  </base-card>
</template>

<script>
import BaseCard from "./Base/BaseCard.vue";

export default {
  components: {
    BaseCard,
  },
  emits: ["add-new-resource"],
  data() {
    return {
      newResource: {
        title: "",
        description: "",
        link: "",
      },
    };
  },
};
</script>

LearningResources.vue

<template>
  <base-card v-for="resource in learningResources" :key="resource.name">
    <template #header>
      <h3>{{ resource.name }}</h3>
      <button @click="$emit('delete-resource', resource.name)">Delete</button>
    </template>

    <template #default>
      <p>{{ resource.description }}</p>
      <p><a :href="resource.link">View Resource</a></p>
    </template>
  </base-card>
</template>

<script>
import BaseCard from "./Base/BaseCard.vue";

export default {
  components: {
    BaseCard,
  },
  props: {
    learningResources: Array,
  },
  emits: ["deleteResource"],
};
</script>

似乎是因为 <component> 被用于两个独立的组件,它们都不会发出与另一个相同的事件。

您可以尝试的一件事是 disabling each components' attribute inheritance:

export default {
    ...
    inheritAttrs: false
    ...
}

如果这不符合您的需要,您可以重构逻辑来处理两个已发出的事件,即将事件重命名为共享名称,如 "addOrDeleteResource",然后确定哪个事件正在 App.vue 并相应地处理它。