• 从$emit 到 父子组件通信 再到 eventBus


    故事还是得从$emit说起,某一天翻文档的时候看到$emit的说明

    触发当前实例上的事件?就是自身组件上的事件呗,在父子组件通信中,父组件通过props传递给子组件数据(高阶组件可以用provide和inject),由于这是单向数据流,为了保证复用组件的的时候出现数据错乱。

    那么只能通过在子组件里面去触发一个事件,来让父组件自己更新数据。

    那么问题来了,$emit不是说好的触发当前实例上的事件吗?那是怎么去能触发父组件数据更新的呢?难道父组件里也能$on对应的事件???

    其实不是的,看下面这个示例

        <div id="app1">
            <m-area :v="value" @do="pAdd"></m-area>
        </div>
        <script src="js/vue.js"></script>
        <script>
            Vue.component('mArea', {
                props: ['v'],
                template: `
                    <div>
                        <button @click="add">{{v}}</button>
                    </div>
                `,
                methods: {
                    add() {
                        this.$emit('do');
                        console.log(this.v)
                    }
                }
            });
            let app1 = new Vue({
                el: '#app1',
                data: {
                    value: 1
                },
                methods: {
                    pAdd() {
                        this.value++;
                    },
                    mouseover() {
                        console.log(this.value);
                    }
                }
            });
        </script>
    

    其实Button 的add方法是只触发了它自身的do事件,但是

     <div id="app1">
            <m-area :v="value" @do="pAdd"></m-area>
     </div>
    

    mArea标签就是该组件啊,do事件是只触发了自身的事件,但是m-area标签是暴露在父组件里的,看看pAdd方法,它是父组件的mthods里的一个方法。由此刚好触发自身组件事件的时候,又触发了父组件里的一个方法,数据可以传参,最终达到更新父组件数据的目的。

    接下来说说eventBus

    一般都是创建一个bus.js,然后 export default new Vue()

    其实背后就是个原理,通过bus.$emit然后涉及到原型链查找,相当于直接是针对于根组件App执行的$emit和$on,站在一个上帝视角,最顶层的组件上,就能形成一个事件总线,这样不同的兄弟组件之间就能进行通信了。

    顺便可以看看vue-bus这个插件的源码,其实也是这么实现的,然后是通过更改get,改了一下调用属性方法的别名而已,然后挂到vue.prototype上,方便全局调用。

    /**
     * vue-bus v1.1.0
     * https://github.com/yangmingshan/vue-bus
     * @license MIT
     */
    (function (global, factory) {
    	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    	typeof define === 'function' && define.amd ? define(factory) :
    	(global.VueBus = factory());
    }(this, (function () { 'use strict';
    
    function VueBus(Vue) {
      var bus = new Vue();
    
      Object.defineProperties(bus, {
        on: {
          get: function get() {
            return this.$on
          }
        },
        once: {
          get: function get() {
            return this.$once
          }
        },
        off: {
          get: function get() {
            return this.$off
          }
        },
        emit: {
          get: function get() {
            return this.$emit
          }
        }
      });
    
      Vue.bus = bus;
      Object.defineProperty(Vue.prototype, '$bus', {
        get: function get() {
          return bus
        }
      });
    }
    
    if (typeof window !== 'undefined' && window.Vue) {
      window.Vue.use(VueBus);
    }
    
    return VueBus;
    
    })));
    

      

      

      

      

  • 相关阅读:
    除了Web和Node,JavaScript还能做什么
    从Hybrid到React-Native: JS在移动端的南征北战史
    当React开发者初次走进React-Native的世界
    【React-Native】React-Native组件样式合集
    【github】论怎么去写一个高大上的ReadMe
    https://github.com/sindresorhus/awesome-nodejs 清单
    https://github.com/akullpp/awesome-java 清单
    https://github.com/ChristosChristofidis/awesome-deep-learning 清单
    https://github.com/josephmisiti/awesome-machine-learning 清单
    SpringBoot 为什么能够自动的注入一些常用的Bean ?详细分析SpringBoot 自动配置的实现
  • 原文地址:https://www.cnblogs.com/hjj2ldq/p/9570269.html
Copyright © 2020-2023  润新知