vue 源碼 event

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

了解vue上的

$on, $emit,  $once,  $off
//剛開始初執(zhí)行
eventsMixin(Vue);
......
//這里我們查看對(duì)應(yīng)的函數(shù)部分
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
  };
}

下面面這樣寫實(shí)際上已經(jīng)執(zhí)行了Vue.prototype.$on

<div id ="app">
    <HelloWorld @showCityName="clickHanlder" msg="Welcome to Your Vue.js App"/>
</div>

export default {
.....
   methods: {
    clickHanlder(data){
     //這里的data就是下面子組件用$emit調(diào)用這個(gè)event時(shí)傳過的參數(shù) {a:10}
      alert(data.a)
    }
   }
}
Vue.prototype.$on = function (event, fn) {
    ......
    console.log(event)
    // 這里的event 就是showCityName
    .....
}

然后在子組件即HelloWorld中我們可以用Vue.prototype.emit來觸發(fā)上面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調(diào)用父組件的 showCityName事件,并傳參過去
      this.$emit('showCityName',{a:10})
    }
  }
}
</script>

從上面的事件中我們可以了解以:

1.vue中用on定義的事件,可以在子組件中用vue中的emit直接調(diào)用并傳參給$on定義的事件

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

3. $off :

. vue把事件添加到一個(gè)數(shù)組隊(duì)列里面,通過刪除該數(shù)組事件隊(duì)列,而達(dá)到解綁事件
.移除自定義事件監(jiān)聽器。
.如果沒有提供參數(shù),則移除所有的事件監(jiān)聽器;
.如果只提供了事件,則移除該事件所有的監(jiān)聽器;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容