github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/src/instance/api/events.js (about)

     1  import { toArray } from '../../util/index'
     2  
     3  export default function (Vue) {
     4    /**
     5     * Listen on the given `event` with `fn`.
     6     *
     7     * @param {String} event
     8     * @param {Function} fn
     9     */
    10  
    11    Vue.prototype.$on = function (event, fn) {
    12      (this._events[event] || (this._events[event] = []))
    13        .push(fn)
    14      modifyListenerCount(this, event, 1)
    15      return this
    16    }
    17  
    18    /**
    19     * Adds an `event` listener that will be invoked a single
    20     * time then automatically removed.
    21     *
    22     * @param {String} event
    23     * @param {Function} fn
    24     */
    25  
    26    Vue.prototype.$once = function (event, fn) {
    27      var self = this
    28      function on () {
    29        self.$off(event, on)
    30        fn.apply(this, arguments)
    31      }
    32      on.fn = fn
    33      this.$on(event, on)
    34      return this
    35    }
    36  
    37    /**
    38     * Remove the given callback for `event` or all
    39     * registered callbacks.
    40     *
    41     * @param {String} event
    42     * @param {Function} fn
    43     */
    44  
    45    Vue.prototype.$off = function (event, fn) {
    46      var cbs
    47      // all
    48      if (!arguments.length) {
    49        if (this.$parent) {
    50          for (event in this._events) {
    51            cbs = this._events[event]
    52            if (cbs) {
    53              modifyListenerCount(this, event, -cbs.length)
    54            }
    55          }
    56        }
    57        this._events = {}
    58        return this
    59      }
    60      // specific event
    61      cbs = this._events[event]
    62      if (!cbs) {
    63        return this
    64      }
    65      if (arguments.length === 1) {
    66        modifyListenerCount(this, event, -cbs.length)
    67        this._events[event] = null
    68        return this
    69      }
    70      // specific handler
    71      var cb
    72      var i = cbs.length
    73      while (i--) {
    74        cb = cbs[i]
    75        if (cb === fn || cb.fn === fn) {
    76          modifyListenerCount(this, event, -1)
    77          cbs.splice(i, 1)
    78          break
    79        }
    80      }
    81      return this
    82    }
    83  
    84    /**
    85     * Trigger an event on self.
    86     *
    87     * @param {String|Object} event
    88     * @return {Boolean} shouldPropagate
    89     */
    90  
    91    Vue.prototype.$emit = function (event) {
    92      var isSource = typeof event === 'string'
    93      event = isSource
    94        ? event
    95        : event.name
    96      var cbs = this._events[event]
    97      var shouldPropagate = isSource || !cbs
    98      if (cbs) {
    99        cbs = cbs.length > 1
   100          ? toArray(cbs)
   101          : cbs
   102        // this is a somewhat hacky solution to the question raised
   103        // in #2102: for an inline component listener like <comp @test="doThis">,
   104        // the propagation handling is somewhat broken. Therefore we
   105        // need to treat these inline callbacks differently.
   106        var hasParentCbs = isSource && cbs.some(function (cb) {
   107          return cb._fromParent
   108        })
   109        if (hasParentCbs) {
   110          shouldPropagate = false
   111        }
   112        var args = toArray(arguments, 1)
   113        for (var i = 0, l = cbs.length; i < l; i++) {
   114          var cb = cbs[i]
   115          var res = cb.apply(this, args)
   116          if (res === true && (!hasParentCbs || cb._fromParent)) {
   117            shouldPropagate = true
   118          }
   119        }
   120      }
   121      return shouldPropagate
   122    }
   123  
   124    /**
   125     * Recursively broadcast an event to all children instances.
   126     *
   127     * @param {String|Object} event
   128     * @param {...*} additional arguments
   129     */
   130  
   131    Vue.prototype.$broadcast = function (event) {
   132      var isSource = typeof event === 'string'
   133      event = isSource
   134        ? event
   135        : event.name
   136      // if no child has registered for this event,
   137      // then there's no need to broadcast.
   138      if (!this._eventsCount[event]) return
   139      var children = this.$children
   140      var args = toArray(arguments)
   141      if (isSource) {
   142        // use object event to indicate non-source emit
   143        // on children
   144        args[0] = { name: event, source: this }
   145      }
   146      for (var i = 0, l = children.length; i < l; i++) {
   147        var child = children[i]
   148        var shouldPropagate = child.$emit.apply(child, args)
   149        if (shouldPropagate) {
   150          child.$broadcast.apply(child, args)
   151        }
   152      }
   153      return this
   154    }
   155  
   156    /**
   157     * Recursively propagate an event up the parent chain.
   158     *
   159     * @param {String} event
   160     * @param {...*} additional arguments
   161     */
   162  
   163    Vue.prototype.$dispatch = function (event) {
   164      var shouldPropagate = this.$emit.apply(this, arguments)
   165      if (!shouldPropagate) return
   166      var parent = this.$parent
   167      var args = toArray(arguments)
   168      // use object event to indicate non-source emit
   169      // on parents
   170      args[0] = { name: event, source: this }
   171      while (parent) {
   172        shouldPropagate = parent.$emit.apply(parent, args)
   173        parent = shouldPropagate
   174          ? parent.$parent
   175          : null
   176      }
   177      return this
   178    }
   179  
   180    /**
   181     * Modify the listener counts on all parents.
   182     * This bookkeeping allows $broadcast to return early when
   183     * no child has listened to a certain event.
   184     *
   185     * @param {Vue} vm
   186     * @param {String} event
   187     * @param {Number} count
   188     */
   189  
   190    var hookRE = /^hook:/
   191    function modifyListenerCount (vm, event, count) {
   192      var parent = vm.$parent
   193      // hooks do not get broadcasted so no need
   194      // to do bookkeeping for them
   195      if (!parent || !count || hookRE.test(event)) return
   196      while (parent) {
   197        parent._eventsCount[event] =
   198          (parent._eventsCount[event] || 0) + count
   199        parent = parent.$parent
   200      }
   201    }
   202  }