Skip to content

Commit d167b9b

Browse files
authored
feat: support Vue3 style app-level provide (#945)
1 parent 032f2c7 commit d167b9b

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

src/apis/createApp.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { VueConstructor } from 'vue'
33
import { Directive } from '../component/directives'
44
import { getVueConstructor } from '../runtimeContext'
55
import { warn } from '../utils'
6+
import { InjectionKey } from './inject'
67

78
// Has a generic to match Vue 3 API and be type compatible
89
export interface App<T = any> {
@@ -12,6 +13,7 @@ export interface App<T = any> {
1213
component: VueConstructor['component']
1314
directive(name: string): Directive | undefined
1415
directive(name: string, directive: Directive): this
16+
provide<T>(key: InjectionKey<T> | symbol | string, value: T): this
1517
mount: Vue['$mount']
1618
unmount: Vue['$destroy']
1719
}
@@ -21,11 +23,17 @@ export function createApp(rootComponent: any, rootProps: any = undefined): App {
2123

2224
let mountedVM: Vue | undefined = undefined
2325

26+
let provide: Record<any, any> = {}
27+
2428
const app: App = {
2529
config: V.config,
2630
use: V.use.bind(V),
2731
mixin: V.mixin.bind(V),
2832
component: V.component.bind(V),
33+
provide<T>(key: InjectionKey<T> | symbol | string, value: T) {
34+
provide[key as any] = value
35+
return this
36+
},
2937
directive(name: string, dir?: Directive | undefined): any {
3038
if (dir) {
3139
V.directive(name, dir as any)
@@ -36,7 +44,11 @@ export function createApp(rootComponent: any, rootProps: any = undefined): App {
3644
},
3745
mount: (el, hydrating) => {
3846
if (!mountedVM) {
39-
mountedVM = new V({ propsData: rootProps, ...rootComponent })
47+
mountedVM = new V({
48+
propsData: rootProps,
49+
...rootComponent,
50+
provide: { ...provide, ...rootComponent.provide },
51+
})
4052
mountedVM.$mount(el, hydrating)
4153
return mountedVM
4254
} else {

test/createApp.spec.ts

+41
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,45 @@ describe('createApp', () => {
6262
await nextTick()
6363
expect(vm.$el.textContent).toBe('foobar')
6464
})
65+
66+
it('should work with provide', async () => {
67+
const Foo = defineComponent({
68+
inject: ['msg'],
69+
template: '<p>{{msg}}</p>',
70+
})
71+
72+
const app = createApp(
73+
defineComponent({
74+
template: '<Foo />',
75+
components: { Foo },
76+
})
77+
)
78+
app.provide('msg', 'foobar')
79+
const vm = app.mount()
80+
81+
await nextTick()
82+
expect(vm.$el.textContent).toBe('foobar')
83+
})
84+
85+
it("should respect root component's provide", async () => {
86+
const Foo = defineComponent({
87+
inject: ['msg'],
88+
template: '<p>{{msg}}</p>',
89+
})
90+
91+
const app = createApp(
92+
defineComponent({
93+
template: '<Foo />',
94+
provide: {
95+
msg: 'root component',
96+
},
97+
components: { Foo },
98+
})
99+
)
100+
app.provide('msg', 'application')
101+
const vm = app.mount()
102+
103+
await nextTick()
104+
expect(vm.$el.textContent).toBe('root component')
105+
})
65106
})

0 commit comments

Comments
 (0)