diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index 41ce25fdfae..05cb3e608cf 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -799,6 +799,88 @@ describe('api: options', () => { ]) }) + test('extends in mixins', () => { + const calls: string[] = [] + const BaseA = { + beforeCreate() { + calls.push('beforeCreateA') + }, + created() { + calls.push('createdA') + } + } + const MixinB = { + mixins: [BaseA], + beforeCreate() { + calls.push('beforeCreateB') + }, + created() { + calls.push('createdB') + } + } + const Comp = { + extends: MixinB, + beforeCreate() { + calls.push('selfBeforeCreate') + }, + created() { + calls.push('selfCreated') + }, + render() {} + } + + renderToString(h(Comp)) + expect(calls).toEqual([ + 'beforeCreateA', + 'beforeCreateB', + 'selfBeforeCreate', + 'createdA', + 'createdB', + 'selfCreated' + ]) + }) + + test('mixins in extends', () => { + const calls: string[] = [] + const BaseA = { + beforeCreate() { + calls.push('beforeCreateA') + }, + created() { + calls.push('createdA') + } + } + const ExtendB = { + extends: BaseA, + beforeCreate() { + calls.push('beforeCreateB') + }, + created() { + calls.push('createdB') + } + } + const Comp = { + mixins: [ExtendB], + beforeCreate() { + calls.push('selfBeforeCreate') + }, + created() { + calls.push('selfCreated') + }, + render() {} + } + + renderToString(h(Comp)) + expect(calls).toEqual([ + 'beforeCreateA', + 'beforeCreateB', + 'selfBeforeCreate', + 'createdA', + 'createdB', + 'selfCreated' + ]) + }) + test('flatten merged options', async () => { const MixinBase = { msg1: 'base' diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 70948d41cf9..462134fa138 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -839,12 +839,15 @@ function callHookFromExtends( if (base.extends) { callHookFromExtends(name, type, base.extends, instance) } + if (base.mixins) { + callHookFromMixins(name, type, base.mixins, instance) + } + const baseHook = base[name] if (baseHook) { callWithAsyncErrorHandling(baseHook.bind(instance.proxy!), instance, type) } } - function callHookFromMixins( name: 'beforeCreate' | 'created', type: LifecycleHooks, @@ -856,6 +859,10 @@ function callHookFromMixins( if (chainedMixins) { callHookFromMixins(name, type, chainedMixins, instance) } + const chainedExtends = mixins[i].extends + if (chainedExtends) { + callHookFromExtends(name, type, chainedExtends, instance) + } const fn = mixins[i][name] if (fn) { callWithAsyncErrorHandling(fn.bind(instance.proxy!), instance, type)