2017-07-14 159 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>