mirror of https://github.com/vuejs/vue.git
no longer need an internal emitter
This commit is contained in:
parent
c4412b55e2
commit
01e6e9ef77
|
|
@ -45,7 +45,6 @@
|
|||
"src/directives/text.js",
|
||||
"src/directives/transition.js",
|
||||
"src/directives/with.js",
|
||||
"src/emitter.js",
|
||||
"src/filters/array-filters.js",
|
||||
"src/filters/index.js",
|
||||
"src/instance/events.js",
|
||||
|
|
|
|||
|
|
@ -1,18 +1,102 @@
|
|||
var _ = require('../util')
|
||||
|
||||
/**
|
||||
* Proxy basic event methods on the internal emitter.
|
||||
* Listen on the given `event` with `fn`.
|
||||
*
|
||||
* @param {String} event
|
||||
* @param {Function} fn
|
||||
*/
|
||||
|
||||
;['emit', 'on', 'off', 'once'].forEach(function (method) {
|
||||
var realMethod = method === 'emit'
|
||||
? 'applyEmit'
|
||||
: method
|
||||
exports['$' + method] = function () {
|
||||
this._emitter[realMethod].apply(
|
||||
this._emitter,
|
||||
arguments
|
||||
)
|
||||
exports.$on = function (event, fn) {
|
||||
(this._events[event] || (this._events[event] = []))
|
||||
.push(fn)
|
||||
// increment all parent event count by 1.
|
||||
// pay a small cost here to optimize for $broadcast.
|
||||
var parent = this.$parent
|
||||
while (parent) {
|
||||
parent._eventsCount[event] =
|
||||
(parent._eventsCount[event] || 0) + 1
|
||||
parent = parent.$parent
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an `event` listener that will be invoked a single
|
||||
* time then automatically removed.
|
||||
*
|
||||
* @param {String} event
|
||||
* @param {Function} fn
|
||||
*/
|
||||
|
||||
exports.$once = function (event, fn) {
|
||||
var self = this
|
||||
function on () {
|
||||
self.$off(event, on)
|
||||
fn.apply(this, arguments)
|
||||
}
|
||||
on.fn = fn
|
||||
this.$on(event, on)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the given callback for `event` or all
|
||||
* registered callbacks.
|
||||
*
|
||||
* @param {String} event
|
||||
* @param {Function} fn
|
||||
*/
|
||||
|
||||
exports.$off = function (event, fn) {
|
||||
// all
|
||||
if (!arguments.length) {
|
||||
this._events = {}
|
||||
return
|
||||
}
|
||||
// specific event
|
||||
var cbs = this._events[event]
|
||||
if (!cbs) return
|
||||
if (arguments.length === 1) {
|
||||
this._events[event] = null
|
||||
return
|
||||
}
|
||||
// specific handler
|
||||
var cb
|
||||
var i = cbs.length
|
||||
while (i--) {
|
||||
cb = cbs[i]
|
||||
if (cb === fn || cb.fn === fn) {
|
||||
cbs.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger an event on self.
|
||||
*
|
||||
* @param {String} event
|
||||
*/
|
||||
|
||||
exports.$emit = function (event) {
|
||||
this._cancelled = false
|
||||
var cbs = this._events[event]
|
||||
if (cbs) {
|
||||
// avoid leaking arguments:
|
||||
// http://jsperf.com/closure-with-arguments
|
||||
var i = arguments.length - 1
|
||||
var args = new Array(i)
|
||||
while (i--) {
|
||||
args[i] = arguments[i + 1]
|
||||
}
|
||||
cbs = _.toArray(cbs)
|
||||
i = 0
|
||||
for (var l = cbs.length; i < l; i++) {
|
||||
if (cbs[i].apply(this, args) === false) {
|
||||
this._eventCancelled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively broadcast an event to all children instances.
|
||||
|
|
@ -21,13 +105,15 @@
|
|||
* @param {...*} additional arguments
|
||||
*/
|
||||
|
||||
exports.$broadcast = function () {
|
||||
exports.$broadcast = function (event) {
|
||||
// if no child has registered for this event,
|
||||
// then there's no need to broadcast.
|
||||
if (!this._eventsCount[event]) return
|
||||
var children = this._children
|
||||
for (var i = 0, l = children.length; i < l; i++) {
|
||||
var child = children[i]
|
||||
var emitter = child._emitter
|
||||
emitter.applyEmit.apply(emitter, arguments)
|
||||
if (!emitter._cancelled) {
|
||||
if (children) {
|
||||
for (var i = 0, l = children.length; i < l; i++) {
|
||||
var child = children[i]
|
||||
child.$emit.apply(child, arguments)
|
||||
child.$broadcast.apply(child, arguments)
|
||||
}
|
||||
}
|
||||
|
|
@ -41,12 +127,9 @@ exports.$broadcast = function () {
|
|||
*/
|
||||
|
||||
exports.$dispatch = function () {
|
||||
var emitter = this._emitter
|
||||
emitter.applyEmit.apply(emitter, arguments)
|
||||
if (!emitter._cancelled) {
|
||||
var parent = this.$parent
|
||||
if (parent) {
|
||||
parent.$dispatch.apply(parent, arguments)
|
||||
}
|
||||
var parent = this.$parent
|
||||
while (parent) {
|
||||
parent.$emit.apply(parent, arguments)
|
||||
parent = parent.$parent
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ exports.$mount = function (el) {
|
|||
this._callHook('attached')
|
||||
ready.call(this)
|
||||
} else {
|
||||
this._emitter.once('hook:attached', ready)
|
||||
this.$once('hook:attached', ready)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,6 +133,5 @@ exports.$destroy = function (remove) {
|
|||
this._isDestroyed = true
|
||||
this._callHook('afterDestroy')
|
||||
// turn off all instance listeners.
|
||||
this._emitter.off()
|
||||
this._emitter = null
|
||||
this.$off()
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ module.exports = {
|
|||
|
||||
bind: function () {
|
||||
var el = this.el
|
||||
this.vm._emitter.once('hook:compiled', function () {
|
||||
this.vm.$once('hook:compiled', function () {
|
||||
el.removeAttribute(config.prefix + 'cloak')
|
||||
})
|
||||
}
|
||||
|
|
|
|||
143
src/emitter.js
143
src/emitter.js
|
|
@ -1,143 +0,0 @@
|
|||
var _ = require('./util')
|
||||
|
||||
/**
|
||||
* Simple event emitter based on component/emitter.
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} ctx - the context to call listners with.
|
||||
*/
|
||||
|
||||
function Emitter (ctx) {
|
||||
this._cancelled = false
|
||||
this._ctx = ctx || null
|
||||
}
|
||||
|
||||
var p = Emitter.prototype
|
||||
|
||||
/**
|
||||
* Listen on the given `event` with `fn`.
|
||||
*
|
||||
* @param {String} event
|
||||
* @param {Function} fn
|
||||
* @return {Emitter}
|
||||
*/
|
||||
|
||||
p.on = function (event, fn) {
|
||||
this._cbs = this._cbs || {}
|
||||
;(this._cbs[event] || (this._cbs[event] = []))
|
||||
.push(fn)
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an `event` listener that will be invoked a single
|
||||
* time then automatically removed.
|
||||
*
|
||||
* @param {String} event
|
||||
* @param {Function} fn
|
||||
* @return {Emitter}
|
||||
*/
|
||||
|
||||
p.once = function (event, fn) {
|
||||
var self = this
|
||||
this._cbs = this._cbs || {}
|
||||
function on () {
|
||||
self.off(event, on)
|
||||
fn.apply(this, arguments)
|
||||
}
|
||||
on.fn = fn
|
||||
this.on(event, on)
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the given callback for `event` or all
|
||||
* registered callbacks.
|
||||
*
|
||||
* @param {String} event
|
||||
* @param {Function} fn
|
||||
* @return {Emitter}
|
||||
*/
|
||||
|
||||
p.off = function (event, fn) {
|
||||
this._cbs = this._cbs || {}
|
||||
// all
|
||||
if (!arguments.length) {
|
||||
this._cbs = {}
|
||||
return this
|
||||
}
|
||||
// specific event
|
||||
var callbacks = this._cbs[event]
|
||||
if (!callbacks) return this
|
||||
// remove all handlers
|
||||
if (arguments.length === 1) {
|
||||
this._cbs[event] = null
|
||||
return this
|
||||
}
|
||||
// remove specific handler
|
||||
var cb
|
||||
var i = callbacks.length
|
||||
while (i--) {
|
||||
cb = callbacks[i]
|
||||
if (cb === fn || cb.fn === fn) {
|
||||
callbacks.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* The internal, faster emit with fixed amount of arguments
|
||||
* using Function.call. This emit assumes that callbacks
|
||||
* triggered will not modify the callback list being
|
||||
* iterated through.
|
||||
*
|
||||
* @param {Object} event
|
||||
* @return {Emitter}
|
||||
*/
|
||||
|
||||
p.emit = function (event, a, b, c, d) {
|
||||
this._cbs = this._cbs || {}
|
||||
var callbacks = this._cbs[event]
|
||||
if (callbacks) {
|
||||
var ctx = this._ctx
|
||||
for (var i = 0, l = callbacks.length; i < l; i++) {
|
||||
callbacks[i].call(ctx, a, b, c, d)
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* The external emit using Function.apply, used
|
||||
* by Vue instance event methods.
|
||||
*
|
||||
* @param {Object} event
|
||||
* @return {Emitter}
|
||||
*/
|
||||
|
||||
p.applyEmit = function (event) {
|
||||
this._cancelled = false
|
||||
this._cbs = this._cbs || {}
|
||||
var callbacks = this._cbs[event]
|
||||
if (callbacks) {
|
||||
// avoid leaking arguments:
|
||||
// http://jsperf.com/closure-with-arguments
|
||||
var i = arguments.length - 1
|
||||
var args = new Array(i)
|
||||
while (i--) {
|
||||
args[i] = arguments[i + 1]
|
||||
}
|
||||
callbacks = _.toArray(callbacks)
|
||||
i = 0
|
||||
for (var l = callbacks.length; i < l; i++) {
|
||||
if (callbacks[i].apply(this._ctx, args) === false) {
|
||||
this._cancelled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
module.exports = Emitter
|
||||
|
|
@ -8,7 +8,6 @@ var inDoc = require('../util').inDoc
|
|||
|
||||
exports._initEvents = function () {
|
||||
var options = this.$options
|
||||
var emitter = this._emitter
|
||||
var events = options.events
|
||||
var methods = options.methods
|
||||
if (events) {
|
||||
|
|
@ -19,7 +18,7 @@ exports._initEvents = function () {
|
|||
var handler = typeof handlers[i] === 'string'
|
||||
? methods && methods[handlers[i]]
|
||||
: handlers[i]
|
||||
emitter.on(e, handler)
|
||||
this.$on(e, handler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,8 +29,7 @@ exports._initEvents = function () {
|
|||
*/
|
||||
|
||||
exports._initDOMHooks = function () {
|
||||
var emitter = this._emitter
|
||||
emitter.on('hook:attached', function () {
|
||||
this.$on('hook:attached', function () {
|
||||
this._isAttached = true
|
||||
var children = this._children
|
||||
if (!children) return
|
||||
|
|
@ -42,7 +40,7 @@ exports._initDOMHooks = function () {
|
|||
}
|
||||
}
|
||||
})
|
||||
emitter.on('hook:detached', function () {
|
||||
this.$on('hook:detached', function () {
|
||||
this._isAttached = false
|
||||
var children = this._children
|
||||
if (!children) return
|
||||
|
|
@ -68,5 +66,5 @@ exports._callHook = function (hook) {
|
|||
handlers[i].call(this)
|
||||
}
|
||||
}
|
||||
this._emitter.emit('hook:' + hook)
|
||||
this.$emit('hook:' + hook)
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
var Emitter = require('../emitter')
|
||||
var mergeOptions = require('../util/merge-option')
|
||||
|
||||
/**
|
||||
|
|
@ -17,13 +16,17 @@ exports._init = function (options) {
|
|||
options = options || {}
|
||||
|
||||
this.$el = null
|
||||
this.$ = {}
|
||||
this.$root = this.$root || this
|
||||
this._emitter = new Emitter(this)
|
||||
this._watchers = Object.create(null)
|
||||
this._userWatchers = Object.create(null)
|
||||
this.$ = {}
|
||||
this._watchers = {}
|
||||
this._userWatchers = {}
|
||||
this._directives = []
|
||||
|
||||
// events bookkeeping
|
||||
this._events = {}
|
||||
this._eventsCount = {}
|
||||
this._eventCancelled = false
|
||||
|
||||
// block instance properties
|
||||
this._blockStart =
|
||||
this._blockEnd = null
|
||||
|
|
|
|||
|
|
@ -18,10 +18,9 @@ var OBJECT = 1
|
|||
* object's property keys into getter/setters that
|
||||
* collect dependencies and dispatches updates.
|
||||
*
|
||||
* @constructor
|
||||
* @extends Emitter
|
||||
* @param {Array|Object} value
|
||||
* @param {Number} type
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
function Observer (value, type) {
|
||||
|
|
@ -190,7 +189,6 @@ p.convert = function (key, val) {
|
|||
binding.notify()
|
||||
}
|
||||
})
|
||||
return binding
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -209,8 +207,8 @@ p.convert = function (key, val) {
|
|||
p.tryRelease = function () {
|
||||
if (!this.parentCount && !this.vmCount) {
|
||||
var value = this.value
|
||||
value.__ob__ = null
|
||||
if (_.isArray(value)) {
|
||||
value.__ob__.bindings = null
|
||||
this.unobserveArray(value)
|
||||
} else {
|
||||
for (var key in value) {
|
||||
|
|
@ -220,6 +218,7 @@ p.tryRelease = function () {
|
|||
_.define(value, key, val, true)
|
||||
}
|
||||
}
|
||||
value.__ob__ = null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue