vue组件通信

85 阅读1分钟

提要

在当前组件使用$on监听$emit事件,$on事件有时不确定何时会触发事件,一般会在mounted或created钩子中来监听。

实现dispatch 和 broadcast方法

  • 在子组件调用dispatch方法,向上级指定的组件实例(最近的)上出发自定义事件,并传递数据,且该上级组件已预先通过$on监听了这个事件;
  • 在父组件调用broadcast方法,向下级指定的组件实例(最近的)上触发自定义事件,并传递数据,且该下级组件已预先通过$on监听了这个事件。

emitter.js

function broadcast(componentName, eventName, params) {
    this.$children.forEach(child => {
        const name = child.$options.name;
        
        if (name === componentName) {
            child.$emit.apply(child, [eventName].concat(params));
        } else {
            broadcast.apply(child, [componentName, eventName].concat([params]));
        }
    });
}

export default {
    methods: {
        // 向上派发自定义事件
        dispatch(componentName, eventName, params) {
            let parent = this.$parent || this.$root;
            let name = parent.$options.name;
            
            while (parent && (!name || name !== componentName)) {
                parent = parent.$parent;
                
                if (parent) {
                    name = parent.$options.name;
                }
            }
            
            if (parent) {
                parent.$emit.apply(parent, [eventName].concat(parent));
            }
        },
        // 向下广播自定义事件
        broadcast(componentName, eventName, params) {
            broadcast.call(this, componentName, eventName, params);
        },
    }
}

实例

<!-- A.vue -->
<template>
    <button @click="handleClick">触发事件</button>
</template>
<script>
    import Emitter from '../mixins/emitter.js';
    
    export default {
        name: 'componentA',
        mixins: [Emitter],
        methods: {
            handleClick () {
                this.broadcast('componentB', 'on-message', 'hello Vue.js');
            }
        }
    }
</script>
<!-- B.vue -->
<script>
    export default {
        name: 'componentB',
        created () {
            this.$on('on-message', this.showMessage);
        },
        methods: {
            showMessage (text) {
                window.alert(text);
            }
        }
    }
</script>

同理,如果B向A通信,在B中调用dispatch方法,在A中使用$on监听事件即可。