1. 程式人生 > >Vue公共廣播/父子元件廣播 $emit、$on的實現及原理解答

Vue公共廣播/父子元件廣播 $emit、$on的實現及原理解答

vm.$emit( event, […args] )

  • 引數:

    • {string} event

    • [...args]

    • 觸發當前例項上的事件。附加引數都會傳給監聽器回撥

m.$on( event, callback )

  • 引數:

    • {string | Array<string>} event (陣列只在 2.2.0+ 中支援)
    • {Function} callback
  • 用法:

    監聽當前例項上的自定義事件。事件可以由vm.$emit觸發。回撥函式會接收所有傳入事件觸發函式的額外引數。

  • 示例:

vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
  • 應用一
// index.vue
<template>
    <div>
        <my-dialog @change-data="receiveDate"></my-dialog>
    </div>
</template>
<script>
    import myDialog from './myDialog'
    export default {
        components: {
            myDialog
        },
        methods: {
            receiveDate (val) {
                            console.log(val) // params
                       }
        }
    }
</script>
// myDialog.vue
<template>
    <div>
        <div @click="handleClick"></div>
    </div>

</template>

<script>
    export default {
        methods: {
                    handleClick (){
                        let params = ""
                        this.$emit("change-data", params)
                }

            }
    }
</script>
  • 應用二

    • eventHub 檔案裡匯出了一個 new vue 例項 ①
    • 與 main.js 裡 new  vue 例項 ② 是平級的
    • 兩個 vue 例項上都有 $emit $on 方法,但是這個栗子裡的廣播 $emit $on 都只在 vue 例項 ① 上

    • vue 例項 ① 一直在監聽

    • 當 vue 例項 ②  中在滿足某個條件需要觸發廣播時,然後用 vue 例項 ① 上的 $emit (eventHub.$emit)傳送廣播,當 vue 例項 ①  上監聽到時,就用 eventHub.$on 接收這個同名的廣播,然後執行回撥函式,至於回撥函式裡有什麼亦或做了是嗎就與它無關了,因為 vue 例項 ① 只負責監聽和接收廣播。

    • 而且 vue 例項 ① 一直存在不會消失。但是 vue 例項 ② 上由於是單頁面應用,所以各種元件會經常被銷燬或者重建,如果元件被銷燬了,它裡面的廣播也就被銷燬了,所以會導致找不到相對應廣播。

// utils/eventHub.js

import Vue from 'vue'

export default new Vue()  // 什麼都沒有繫結,因為它只是一個跳板,並且在實時監聽
// index.vue
<template>
    <div>
        <my-dialog></my-dialog>
    </div>
</template>
<script>
    import myDialog from './myDialog'
    import eventHub from 'utils/eventHub'

    export default {
        components: {
            myDialog
        },
        mounted() {
            eventHub.$on("change-data", (val) => {
                console.log(val) // params
            })
        },
        beforeDestroy () { // 在例項銷燬之前,移除監聽器
            eventHub.$off("change-data")
        }
     }
</script>

// myDialog.vue
<template>
    <div>
        <div @click="handleClick"></div>
    </div>

</template>
<script>
    import eventHub from 'utils/eventHub'
    export default {
        methods: {
                    handleClick (){
                        let params = ""
                        eventHub.$emit("change-data", params)
                }
            }
    }
</script>
// main.js

new Vue({
    el: '#app',
    router,
    store,
    template: '<app/>',
    components: { app }
})