diff --git a/flow/component.js b/flow/component.js index e3326bd3d0e..6034af5602f 100644 --- a/flow/component.js +++ b/flow/component.js @@ -43,6 +43,7 @@ declare interface Component { $on: (event: string | Array, fn: Function) => Component; $once: (event: string, fn: Function) => Component; $off: (event?: string | Array, fn?: Function) => Component; + $notify: (event: string, ...args: Array) => Array; $emit: (event: string, ...args: Array) => Component; $nextTick: (fn: Function) => void | Promise<*>; $createElement: (tag?: string | Component, data?: Object, children?: VNodeChildren) => VNode; diff --git a/src/core/instance/events.js b/src/core/instance/events.js index 587799969c2..4a44626d3be 100644 --- a/src/core/instance/events.js +++ b/src/core/instance/events.js @@ -111,7 +111,7 @@ export function eventsMixin (Vue: Class) { return vm } - Vue.prototype.$emit = function (event: string): Component { + Vue.prototype.$notify = function (event: string): Array { const vm: Component = this if (process.env.NODE_ENV !== 'production') { const lowerCaseEvent = event.toLowerCase() @@ -126,17 +126,24 @@ export function eventsMixin (Vue: Class) { } } let cbs = vm._events[event] + const retValues: Array = [] if (cbs) { cbs = cbs.length > 1 ? toArray(cbs) : cbs const args = toArray(arguments, 1) + retValues.length = cbs.length for (let i = 0, l = cbs.length; i < l; i++) { try { - cbs[i].apply(vm, args) + retValues[i] = cbs[i].apply(vm, args) } catch (e) { handleError(e, vm, `event handler for "${event}"`) } } } - return vm + return retValues + } + + Vue.prototype.$emit = function (event: string): Component { + Vue.prototype.$notify.apply(this, arguments) + return this } } diff --git a/test/unit/features/directives/on.spec.js b/test/unit/features/directives/on.spec.js index 4ef3c699fe0..44b29d01c38 100644 --- a/test/unit/features/directives/on.spec.js +++ b/test/unit/features/directives/on.spec.js @@ -399,6 +399,38 @@ describe('Directive v-on', () => { Vue.config.keyCodes = Object.create(null) }) + it('should return this for $emit', () => { + vm = new Vue({ + el, + template: '', + methods: { foo: () => 123 }, + components: { + bar: { + template: 'Hello' + } + } + }) + const retValue = vm.$children[0].$emit('custom', 'foo', 'bar') + expect(retValue).toBe(vm.$children[0]) + }) + + it('should return an array for $notify', () => { + vm = new Vue({ + el, + template: '', + methods: { foo: () => 123 }, + components: { + bar: { + template: 'Hello' + } + } + }) + const retValue = vm.$children[0].$notify('custom', 'foo', 'bar') + expect(Array.isArray(retValue)).toBe(true) + expect(retValue.length).toBe(1) + expect(retValue[0]).toBe(123) + }) + it('should bind to a child component', () => { vm = new Vue({ el, diff --git a/types/test/vue-test.ts b/types/test/vue-test.ts index 031a909b67a..9c7a5432866 100644 --- a/types/test/vue-test.ts +++ b/types/test/vue-test.ts @@ -47,6 +47,7 @@ class Test extends Vue { this.$once("", () => {}); this.$off("", () => {}); this.$emit("", 1, 2, 3); + this.$notify("", 1, 2, 3); this.$nextTick(function() { this.$nextTick; }); diff --git a/types/vue.d.ts b/types/vue.d.ts index 045644e0a94..1298a670940 100644 --- a/types/vue.d.ts +++ b/types/vue.d.ts @@ -56,6 +56,7 @@ export interface Vue { $once(event: string, callback: Function): this; $off(event?: string | string[], callback?: Function): this; $emit(event: string, ...args: any[]): this; + $notify(event: string, ...args: any[]): any[]; $nextTick(callback: (this: this) => void): void; $nextTick(): Promise; $createElement: CreateElement;