2017-07-14 23 views
1

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

下面是从控制台的屏幕截图时,我的组件之间进行切换: 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

发生这种情况,因为你不断地添加事件侦听器(当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/[email protected]/dist/vue.js"></script> 
 
<div id="app"> 
 

 
</div>