Vue.js - 具有动态组件的多事件

时间:2017-07-14 13:02:57

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

我有一个简单的根App,其中包含两个不同的组件RoomMachine。并且这些组件中的每一个都包括一个组件Datatable,它们对于它们两者完全相同。要在RoomMachine之间切换,我正在使用动态组件机制,没什么特别的。当组件发生变化时,我只发出事件,而组件Datatable应该使用当前模块名称将其记录在控制台中。问题是每次更改组件时,都会多次发送事件。如果我理解正确,在更改组件后,应该销毁旧组件并创建新组件,以便为什么会发生这种情况?我正在使用Vue.js v.2.4.1

以下是我在组件之间切换时控制台的屏幕截图: enter image description here

以下是组件:

App.vue:

<template>
    <div id="app">
        <select style="padding: 10px" v-model="currentModule" @change="changeComponent">
            <option value="Room">Room</option>
            <option value="Machine">Machine</option>
        </select>
        <component :is="currentModule"></component>
    </div>
</template>

<script>
    import Room from './Room.vue';
    import Machine from './Machine.vue';


    export default {
        name: 'app',
        components: {
            Room,
            Machine
        },
        data () {
            return {
                currentModule: 'Room'
            }
        },
        methods: {
            changeComponent: function() {
                Event.$emit('moduleHasChanged', this.currentModule)
            }
        },
    }
</script>

Machine.vue:

<template>
    <div>
        Machine template

        <datatable></datatable>
    </div>
</template>
<script>
    import Datatable from './Datatable.vue';

    export default {
        components: {
            Datatable
        }
    }
</script>

Room.vue:

<template>
    <div>
        Room template

        <datatable></datatable>
    </div>
</template>
<script>
    import Datatable from './Datatable.vue';

    export default {
        components: {
            Datatable
        }
    }
</script>

Datatable.vue

<template>
    <div>
        Datatable
    </div>
</template>

<script>
    export default {
        created() {
            Event.$on('moduleHasChanged', (currentModule) => {
                console.log(currentModule);
            })
        }
    }
</script>

1 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为您不断添加事件侦听器(创建Datatable组件时)并且永远不会删除它们。 Vue通常会为您处理此问题,但由于您使用的是事件总线,因此您需要自己动手。

只需添加beforeDestroy处理程序并删除事件处理程序。

console.clear()
const Event = new Vue()

const Datatable = {
  template: `
    <div>
      Datatable
    </div>
  `,
  methods: {
    moduleChanged(currentModule) {
      console.log(currentModule);
    }
  },
  created() {
    Event.$on('moduleHasChanged', this.moduleChanged)
  },
  beforeDestroy() {
    Event.$off('moduleHasChanged', this.moduleChanged)
  }
}

const Room = {
  template: `
    <div>
      Room template
      <datatable></datatable>
    </div>
  `,
  components: {
    Datatable
  }
}

const Machine = {
  template: `
    <div>
      Machine template
      <datatable></datatable>
    </div>
  `,
  components: {
    Datatable
  }
}

const App = {
  name: 'app',
  template: `
    <div id="app">
        <select style="padding: 10px" v-model="currentModule" @change="changeComponent">
            <option value="Room">Room</option>
            <option value="Machine">Machine</option>
        </select>
        <component :is="currentModule"></component>
    </div>
  `,
  components: {
    Room,
    Machine
  },
  data() {
    return {
      currentModule: 'Room'
    }
  },
  methods: {
    changeComponent: function() {
      Event.$emit('moduleHasChanged', this.currentModule)
    }
  },
}


new Vue({
  el: "#app",
  render: h => h(App)
})
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">

</div>