@@ -85,21 +85,36 @@ export default function (Vue) {
85
85
/**
86
86
* Trigger an event on self.
87
87
*
88
- * @param {String } event
88
+ * @param {String|Object } event
89
89
* @return {Boolean } shouldPropagate
90
90
*/
91
91
92
92
Vue . prototype . $emit = function ( event ) {
93
+ var isSource = typeof event === 'string'
94
+ event = isSource
95
+ ? event
96
+ : event . name
93
97
var cbs = this . _events [ event ]
94
- var shouldPropagate = ! cbs
98
+ var shouldPropagate = isSource || ! cbs
95
99
if ( cbs ) {
96
100
cbs = cbs . length > 1
97
101
? toArray ( cbs )
98
102
: cbs
103
+ // this is a somewhat hacky solution to the question raised
104
+ // in #2102: for an inline component listener like <comp @test="doThis">,
105
+ // the propagation handling is somewhat broken. Therefore we
106
+ // need to treat these inline callbacks differently.
107
+ var hasParentCbs = isSource && cbs . some ( function ( cb ) {
108
+ return cb . _fromParent
109
+ } )
110
+ if ( hasParentCbs ) {
111
+ shouldPropagate = false
112
+ }
99
113
var args = toArray ( arguments , 1 )
100
114
for ( var i = 0 , l = cbs . length ; i < l ; i ++ ) {
101
- var res = cbs [ i ] . apply ( this , args )
102
- if ( res === true ) {
115
+ var cb = cbs [ i ]
116
+ var res = cb . apply ( this , args )
117
+ if ( res === true && ( ! hasParentCbs || cb . _fromParent ) ) {
103
118
shouldPropagate = true
104
119
}
105
120
}
@@ -110,20 +125,30 @@ export default function (Vue) {
110
125
/**
111
126
* Recursively broadcast an event to all children instances.
112
127
*
113
- * @param {String } event
128
+ * @param {String|Object } event
114
129
* @param {...* } additional arguments
115
130
*/
116
131
117
132
Vue . prototype . $broadcast = function ( event ) {
133
+ var isSource = typeof event === 'string'
134
+ event = isSource
135
+ ? event
136
+ : event . name
118
137
// if no child has registered for this event,
119
138
// then there's no need to broadcast.
120
139
if ( ! this . _eventsCount [ event ] ) return
121
140
var children = this . $children
141
+ var args = toArray ( arguments )
142
+ if ( isSource ) {
143
+ // use object event to indicate non-source emit
144
+ // on children
145
+ args [ 0 ] = { name : event , source : this }
146
+ }
122
147
for ( var i = 0 , l = children . length ; i < l ; i ++ ) {
123
148
var child = children [ i ]
124
- var shouldPropagate = child . $emit . apply ( child , arguments )
149
+ var shouldPropagate = child . $emit . apply ( child , args )
125
150
if ( shouldPropagate ) {
126
- child . $broadcast . apply ( child , arguments )
151
+ child . $broadcast . apply ( child , args )
127
152
}
128
153
}
129
154
return this
@@ -136,11 +161,16 @@ export default function (Vue) {
136
161
* @param {...* } additional arguments
137
162
*/
138
163
139
- Vue . prototype . $dispatch = function ( ) {
140
- this . $emit . apply ( this , arguments )
164
+ Vue . prototype . $dispatch = function ( event ) {
165
+ var shouldPropagate = this . $emit . apply ( this , arguments )
166
+ if ( ! shouldPropagate ) return
141
167
var parent = this . $parent
168
+ var args = toArray ( arguments )
169
+ // use object event to indicate non-source emit
170
+ // on parents
171
+ args [ 0 ] = { name : event , source : this }
142
172
while ( parent ) {
143
- var shouldPropagate = parent . $emit . apply ( parent , arguments )
173
+ shouldPropagate = parent . $emit . apply ( parent , args )
144
174
parent = shouldPropagate
145
175
? parent . $parent
146
176
: null
0 commit comments