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

Posted

技术标签:

【中文标题】Vue.js - 具有动态组件的多个事件【英文标题】:Vue.js - multiple event with dynamic components 【发布时间】:2017-12-19 14:24:57 【问题描述】:

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

这是我在组件之间切换时来自控制台的屏幕截图:

这里是组件:

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】:

发生这种情况是因为您不断添加事件侦听器(在创建 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>

【讨论】:

以上是关于Vue.js - 具有动态组件的多个事件的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js 2使用中的难点举例--子组件,slot, 动态组件,事件监听

在 Vue js 中动态使用多个页面(组件)

使用 Vue js 发布具有多个组件的表单的最佳方式是啥

Vue组件及自定义事件

Vue.js - 具有两行跨度的组件

Vue js - 多个组件,每个组件都有不同的初始选定值