销毁Vue组件的Mixin仍在监听事件

时间:2020-07-20 08:55:55

标签: javascript vue.js vuejs2 vue-component mixins

我有一个父组件,有条件地呈现两个子组件之一:

<template>
  <div>
    <!-- other code that changes conditional rendering -->

    <folders v-if="isSearchingInFolders" :key="1234"></folders>
    <snippets v-if="!isSearchingInFolders" :key="5678"></snippets>
  </div>
</template>

每个组件在本地都使用相同的mixin(searchMixin),如下所示:

<template>
  <div>
    <div>
      <snippet
        v-for="item in items"
        :snippet="item"
        :key="item.id">
      </snippet>
      <img v-if="busy" src="/icons/loader-grey.svg" width="50">
    </div>
    <button @click="getItems">Get More</button>
  </div>
</template>

<script>
import searchMixin from './mixins/searchMixin';
import Snippet from './snippet';

export default {
  components: { Snippet },

  mixins: [searchMixin],

  data() {
    return {
      resourceName: 'snippets'
    }
  },
}
</script>

每个组件在功能上都是等效的,但标记略有不同,因此,出于本示例的目的,可以用片段替换文件夹,反之亦然。

我正在使用的mixin看起来像这样(简化):

import axios from 'axios'
import  { EventBus } from '../event-bus';

export default {

  data() {
    return {
      hasMoreItems: true,
      busy: false,
      items: []
    }
  },

  created() {
    EventBus.$on('search', this.getItems)
    this.getItems();
  },

  destroyed() {
    this.$store.commit('resetSearchParams')
  },

  computed: {
    endpoint() {
      return `/${this.resourceName}/search`
    },

    busyOrMaximum() {
      return this.busy || !this.hasMoreItems;
    }
  },

  methods: {
    getItems(reset = false) {
      <!-- get the items and add them to this.items -->
    }
  }
}

在父组件中,通过更改isSearchingInFolders变量切换渲染时,预期的组件被销毁并从DOM中删除(我通过从destroyed()生命周期钩子中进行记录进行了检查。包含在该组件中的searchMixin似乎没有被破坏,仍然可以监听事件。这意味着,在更改了从父级主动渲染的组件后触发了EventBus.$on('search', this.getItems)行时,{ {1}}被触发两次,一次用于文件夹,另一次用于代码段!

我期望组件的mixins与组件本身一起被销毁。我是否误解了组件破坏的工作原理?

1 个答案:

答案 0 :(得分:1)

是的,在传递事件处理程序时,EventBus会保留对传递给函数的引用。这样可以防止破坏组件对象。因此,您需要通过调用EventBus.$off清除引用,以便可以破坏组件。因此,您的destroy事件挂钩应如下所示:

destroyed() {
    this.$store.commit('resetSearchParams')
    EventBus.$off('search', this.getItems)
  },