diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index 6b6014c05cc..ad2c7106a80 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -324,6 +324,36 @@ describe('api: options', () => { expect(renderToString(h(Root))).toBe(`11112345`) }) + test('provide accessing data in extends', () => { + const Base = defineComponent({ + data() { + return { + a: 1 + } + }, + provide() { + return { + a: this.a + } + } + }) + + const Child = { + inject: ['a'], + render() { + return (this as any).a + } + } + + const Root = defineComponent({ + extends: Base, + render() { + return h(Child) + } + }) + expect(renderToString(h(Root))).toBe(`1`) + }) + test('lifecycle', async () => { const count = ref(0) const root = nodeOps.createElement('div') diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 57bd57e3d85..ee4062ba8b9 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -430,6 +430,7 @@ export function applyOptions( options: ComponentOptions, deferredData: DataFn[] = [], deferredWatch: ComponentWatchOptions[] = [], + deferredProvide: (Data | Function)[] = [], asMixin: boolean = false ) { const { @@ -483,16 +484,29 @@ export function applyOptions( ) isInBeforeCreate = false // global mixins are applied first - applyMixins(instance, globalMixins, deferredData, deferredWatch) + applyMixins( + instance, + globalMixins, + deferredData, + deferredWatch, + deferredProvide + ) } // extending a base component... if (extendsOptions) { - applyOptions(instance, extendsOptions, deferredData, deferredWatch, true) + applyOptions( + instance, + extendsOptions, + deferredData, + deferredWatch, + deferredProvide, + true + ) } // local mixins if (mixins) { - applyMixins(instance, mixins, deferredData, deferredWatch) + applyMixins(instance, mixins, deferredData, deferredWatch, deferredProvide) } const checkDuplicateProperties = __DEV__ ? createDuplicateChecker() : null @@ -634,12 +648,17 @@ export function applyOptions( } if (provideOptions) { - const provides = isFunction(provideOptions) - ? provideOptions.call(publicThis) - : provideOptions - for (const key in provides) { - provide(key, provides[key]) - } + deferredProvide.push(provideOptions) + } + if (!asMixin && deferredProvide.length) { + deferredProvide.forEach(provideOptions => { + const provides = isFunction(provideOptions) + ? provideOptions.call(publicThis) + : provideOptions + for (const key in provides) { + provide(key, provides[key]) + } + }) } // asset options. @@ -777,10 +796,18 @@ function applyMixins( instance: ComponentInternalInstance, mixins: ComponentOptions[], deferredData: DataFn[], - deferredWatch: ComponentWatchOptions[] + deferredWatch: ComponentWatchOptions[], + deferredProvide: (Data | Function)[] ) { for (let i = 0; i < mixins.length; i++) { - applyOptions(instance, mixins[i], deferredData, deferredWatch, true) + applyOptions( + instance, + mixins[i], + deferredData, + deferredWatch, + deferredProvide, + true + ) } }