Vue源碼解析(三)

接下來調用eventsMixin方法,看名稱就知道是關於事件相關的,主要是在Vue的原型上加入$on,$once,$off,$emit方法。

Vue.prototype.$on = function (event, fn) {
    var this$1 = this;

    var vm = this;
    if (Array.isArray(event)) {
      for (var i = 0, l = event.length; i < l; i++) {
        this$1.$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
  };

$on方法爲監聽自定義事件,如果event爲數組,則遍歷event數組進行監聽。如果爲字符串則放入vm._events數組中。這塊還進行了一個事件是否爲Hook的正則判斷,暫未搞清楚具體作用。

Vue.prototype.$off = function (event, fn) {
    var this$1 = this;

    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++) {
        this$1.$off(event[i$1], fn);
      }
      return vm
    }
    // specific event
    var cbs = vm._events[event];
    if (!cbs) {
      return vm
    }
    if (arguments.length === 1) {
      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
  };

$off方法爲解除已綁定的事件,如果off方法不傳任何參數,刪除所有綁定事件。如果event爲數組,則循環解除數組內的事件。如果爲字符串,事件數組不存在則直接返回;如果不需要回調,則將相關事件數組設爲null。如果該事件數組有存在,則遍歷事件數組,並從數組中刪除符合條件的事件。

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
  };

$once方法爲綁定僅響應一次事件,響應結束後立即解除綁定。主要是調用了$on方法,同時回調時調用$off方法解除該事件,並再解除事件後進行回調。

Vue.prototype.$emit = function (event) {
    var vm = this;
    {
      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);
      for (var i = 0, l = cbs.length; i < l; i++) {
        cbs[i].apply(vm, args);
      }
    }
    return vm
  };

$emit方法爲事件下發的方法,首先進行了一個大小寫的判斷,如果註冊事件和下發事件的大小寫不一致,則發出警告。如果該事件數組存在,則遍歷事件數組進行註冊回調,同時使用apply方法傳遞調用時參數。

發佈了48 篇原創文章 · 獲贊 40 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章