美文网首页
vue 源码 event

vue 源码 event

作者: Wendy81 | 来源:发表于2021-01-11 17:10 被阅读0次

    在moduel包中 vue/dist/vue.runtime.esm.js

    了解vue上的

    $on, $emit,  $once,  $off
    
    //刚开始初执行
    eventsMixin(Vue);
    ......
    //这里我们查看对应的函数部分
    function eventsMixin (Vue) {
      var hookRE = /^hook:/;
      Vue.prototype.$on = function (event, fn) {
        var vm = this;
        if (Array.isArray(event)) {
          for (var i = 0, l = event.length; i < l; i++) {
            vm.$on(event[i], fn);
          }
        } else {
          (vm._events[event] || (vm._events[event] = [])).push(fn);
          // optimize hook:event cost by using a boolean flag marked at registration
          // instead of a hash lookup
          if (hookRE.test(event)) {
            vm._hasHookEvent = true;
          }
        }
        return vm
      };
    
      Vue.prototype.$once = function (event, fn) {
        var vm = this;
        function on () {
          vm.$off(event, on);
          fn.apply(vm, arguments);
        }
        on.fn = fn;
        vm.$on(event, on);
        return vm
      };
    
      Vue.prototype.$off = function (event, fn) {
        var vm = this;
        // all
        if (!arguments.length) {
          vm._events = Object.create(null);
          return vm
        }
        // array of events
        if (Array.isArray(event)) {
          for (var i$1 = 0, l = event.length; i$1 < l; i$1++) {
            vm.$off(event[i$1], fn);
          }
          return vm
        }
        // specific event
        var cbs = vm._events[event];
        if (!cbs) {
          return vm
        }
        if (!fn) {
          vm._events[event] = null;
          return vm
        }
        // specific handler
        var cb;
        var i = cbs.length;
        while (i--) {
          cb = cbs[i];
          if (cb === fn || cb.fn === fn) {
            cbs.splice(i, 1);
            break
          }
        }
        return vm
      };
    
      Vue.prototype.$emit = function (event) {
        var vm = this;
        if (process.env.NODE_ENV !== 'production') {
          var lowerCaseEvent = event.toLowerCase();
          if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
            tip(
              "Event \"" + lowerCaseEvent + "\" is emitted in component " +
              (formatComponentName(vm)) + " but the handler is registered for \"" + event + "\". " +
              "Note that HTML attributes are case-insensitive and you cannot use " +
              "v-on to listen to camelCase events when using in-DOM templates. " +
              "You should probably use \"" + (hyphenate(event)) + "\" instead of \"" + event + "\"."
            );
          }
        }
        var cbs = vm._events[event];
        if (cbs) {
          cbs = cbs.length > 1 ? toArray(cbs) : cbs;
          var args = toArray(arguments, 1);
          var info = "event handler for \"" + event + "\"";
          for (var i = 0, l = cbs.length; i < l; i++) {
            invokeWithErrorHandling(cbs[i], vm, args, vm, info);
          }
        }
        return vm
      };
    }
    
    

    下面面这样写实际上已经执行了Vue.prototype.$on

    <div id ="app">
        <HelloWorld @showCityName="clickHanlder" msg="Welcome to Your Vue.js App"/>
    </div>
    
    export default {
    .....
       methods: {
        clickHanlder(data){
         //这里的data就是下面子组件用$emit调用这个event时传过的参数 {a:10}
          alert(data.a)
        }
       }
    }
    
    Vue.prototype.$on = function (event, fn) {
        ......
        console.log(event)
        // 这里的event 就是showCityName
        .....
    }
    

    然后在子组件即HelloWorld中我们可以用Vue.prototype.emit来触发上面Vue.prototype.on定义的事件showCityName

    <template>
      <div id="hello" class="hello">
        <button @click="clickHanlder">click</button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
      methods: {
        clickHanlder(){
          //这里我们可以用$emit调用父组件的 showCityName事件,并传参过去
          this.$emit('showCityName',{a:10})
        }
      }
    }
    </script>
    

    从上面的事件中我们可以了解以:

    1.vue中用on定义的事件,可以在子组件中用vue中的emit直接调用并传参给$on定义的事件

    2.$once : 只添加一次事件

    3. $off :

    . vue把事件添加到一个数组队列里面,通过删除该数组事件队列,而达到解绑事件
    .移除自定义事件监听器。
    .如果没有提供参数,则移除所有的事件监听器;
    .如果只提供了事件,则移除该事件所有的监听器;

    相关文章

      网友评论

          本文标题:vue 源码 event

          本文链接:https://www.haomeiwen.com/subject/hhpdaktx.html