From 394a6d92799c7ebe7447463de336895a58196199 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Wed, 26 Aug 2020 21:15:16 +0800 Subject: [PATCH 1/2] fix(runtime-core): the lifecycle hooks in mixins & extends should be called correctly --- packages/runtime-core/src/componentOptions.ts | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index ff3927004ed..facca201d9e 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -614,11 +614,11 @@ function callSyncHook( globalMixins: ComponentOptions[] ) { callHookFromMixins(name, globalMixins, ctx) - const baseHook = options.extends && options.extends[name] - if (baseHook) { - baseHook.call(ctx) + + const { extends: base, mixins } = options + if (base) { + callHookFromExtends(name, base, ctx) } - const mixins = options.mixins if (mixins) { callHookFromMixins(name, mixins, ctx) } @@ -628,12 +628,30 @@ function callSyncHook( } } +function callHookFromExtends( + name: 'beforeCreate' | 'created', + base: ComponentOptions, + ctx: ComponentPublicInstance +) { + if (base.extends) { + callHookFromExtends(name, base.extends, ctx) + } + const baseHook = base[name] + if (baseHook) { + baseHook.call(ctx) + } +} + function callHookFromMixins( name: 'beforeCreate' | 'created', mixins: ComponentOptions[], ctx: ComponentPublicInstance ) { for (let i = 0; i < mixins.length; i++) { + const chainedMixins = mixins[i].mixins + if (chainedMixins) { + callHookFromMixins(name, chainedMixins, ctx) + } const fn = mixins[i][name] if (fn) { fn.call(ctx) From f8f5931332f1468b500601c69ddba75b043564f4 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Wed, 26 Aug 2020 21:36:47 +0800 Subject: [PATCH 2/2] test: add tests for beforeCreate and created in mixins and extends --- .../runtime-core/__tests__/apiOptions.spec.ts | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index d61d46be363..e3151fbfa42 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -633,6 +633,71 @@ describe('api: options', () => { expect(calls).toEqual(['base', 'mixin', 'comp']) }) + test('beforeCreate/created in extends and mixins', () => { + const calls: string[] = [] + const BaseA = { + beforeCreate() { + calls.push('beforeCreateA') + }, + created() { + calls.push('createdA') + } + } + const BaseB = { + extends: BaseA, + beforeCreate() { + calls.push('beforeCreateB') + }, + created() { + calls.push('createdB') + } + } + + const MixinA = { + beforeCreate() { + calls.push('beforeCreateC') + }, + created() { + calls.push('createdC') + } + } + const MixinB = { + mixins: [MixinA], + beforeCreate() { + calls.push('beforeCreateD') + }, + created() { + calls.push('createdD') + } + } + + const Comp = { + extends: BaseB, + mixins: [MixinB], + beforeCreate() { + calls.push('selfBeforeCreate') + }, + created() { + calls.push('selfCreated') + }, + render() {} + } + + renderToString(h(Comp)) + expect(calls).toEqual([ + 'beforeCreateA', + 'beforeCreateB', + 'beforeCreateC', + 'beforeCreateD', + 'selfBeforeCreate', + 'createdA', + 'createdB', + 'createdC', + 'createdD', + 'selfCreated' + ]) + }) + test('accessing setup() state from options', async () => { const Comp = defineComponent({ setup() {