From 55e7a3bb6d067ac027349e1505bbbd62484e2b80 Mon Sep 17 00:00:00 2001 From: lsdsjy Date: Thu, 23 Jun 2022 11:41:38 +0800 Subject: [PATCH 1/2] feat: support Vue3 style app-level provide --- src/apis/createApp.ts | 14 +++++++++++++- test/createApp.spec.ts | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/apis/createApp.ts b/src/apis/createApp.ts index 4c86dde9..8f3aa208 100644 --- a/src/apis/createApp.ts +++ b/src/apis/createApp.ts @@ -3,6 +3,7 @@ import { VueConstructor } from 'vue' import { Directive } from '../component/directives' import { getVueConstructor } from '../runtimeContext' import { warn } from '../utils' +import { InjectionKey } from './inject' // Has a generic to match Vue 3 API and be type compatible export interface App { @@ -12,6 +13,7 @@ export interface App { component: VueConstructor['component'] directive(name: string): Directive | undefined directive(name: string, directive: Directive): this + provide(key: InjectionKey | symbol | string, value: T): this mount: Vue['$mount'] unmount: Vue['$destroy'] } @@ -21,11 +23,17 @@ export function createApp(rootComponent: any, rootProps: any = undefined): App { let mountedVM: Vue | undefined = undefined + let provide: Record = {} + const app: App = { config: V.config, use: V.use.bind(V), mixin: V.mixin.bind(V), component: V.component.bind(V), + provide(key: InjectionKey | symbol | string, value: T) { + provide[key as any] = value + return this + }, directive(name: string, dir?: Directive | undefined): any { if (dir) { V.directive(name, dir as any) @@ -36,7 +44,11 @@ export function createApp(rootComponent: any, rootProps: any = undefined): App { }, mount: (el, hydrating) => { if (!mountedVM) { - mountedVM = new V({ propsData: rootProps, ...rootComponent }) + mountedVM = new V({ + propsData: rootProps, + ...rootComponent, + provide: { ...provide, ...rootComponent.provide }, + }) mountedVM.$mount(el, hydrating) return mountedVM } else { diff --git a/test/createApp.spec.ts b/test/createApp.spec.ts index 3c3419a8..8a827cdd 100644 --- a/test/createApp.spec.ts +++ b/test/createApp.spec.ts @@ -62,4 +62,23 @@ describe('createApp', () => { await nextTick() expect(vm.$el.textContent).toBe('foobar') }) + + it('should work with provide', async () => { + const Foo = defineComponent({ + inject: ['msg'], + template: '

{{msg}}

', + }) + + const app = createApp( + defineComponent({ + template: '', + }) + ) + app.component('Foo', Foo) + app.provide('msg', 'foobar') + const vm = app.mount() + + await nextTick() + expect(vm.$el.textContent).toBe('foobar') + }) }) From 7d3356136ae0dc73a620691a86b6c3b3278dec64 Mon Sep 17 00:00:00 2001 From: lsdsjy Date: Thu, 23 Jun 2022 11:50:21 +0800 Subject: [PATCH 2/2] chore: add test case --- test/createApp.spec.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/createApp.spec.ts b/test/createApp.spec.ts index 8a827cdd..097a52c9 100644 --- a/test/createApp.spec.ts +++ b/test/createApp.spec.ts @@ -72,13 +72,35 @@ describe('createApp', () => { const app = createApp( defineComponent({ template: '', + components: { Foo }, }) ) - app.component('Foo', Foo) app.provide('msg', 'foobar') const vm = app.mount() await nextTick() expect(vm.$el.textContent).toBe('foobar') }) + + it("should respect root component's provide", async () => { + const Foo = defineComponent({ + inject: ['msg'], + template: '

{{msg}}

', + }) + + const app = createApp( + defineComponent({ + template: '', + provide: { + msg: 'root component', + }, + components: { Foo }, + }) + ) + app.provide('msg', 'application') + const vm = app.mount() + + await nextTick() + expect(vm.$el.textContent).toBe('root component') + }) })