Skip to content

Commit

Permalink
feat: support Vue3 style app-level provide (#945)
Browse files Browse the repository at this point in the history
  • Loading branch information
lsdsjy committed Jun 24, 2022
1 parent 032f2c7 commit d167b9b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/apis/createApp.ts
Expand Up @@ -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<T = any> {
Expand All @@ -12,6 +13,7 @@ export interface App<T = any> {
component: VueConstructor['component']
directive(name: string): Directive | undefined
directive(name: string, directive: Directive): this
provide<T>(key: InjectionKey<T> | symbol | string, value: T): this
mount: Vue['$mount']
unmount: Vue['$destroy']
}
Expand All @@ -21,11 +23,17 @@ export function createApp(rootComponent: any, rootProps: any = undefined): App {

let mountedVM: Vue | undefined = undefined

let provide: Record<any, any> = {}

const app: App = {
config: V.config,
use: V.use.bind(V),
mixin: V.mixin.bind(V),
component: V.component.bind(V),
provide<T>(key: InjectionKey<T> | 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)
Expand All @@ -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 {
Expand Down
41 changes: 41 additions & 0 deletions test/createApp.spec.ts
Expand Up @@ -62,4 +62,45 @@ describe('createApp', () => {
await nextTick()
expect(vm.$el.textContent).toBe('foobar')
})

it('should work with provide', async () => {
const Foo = defineComponent({
inject: ['msg'],
template: '<p>{{msg}}</p>',
})

const app = createApp(
defineComponent({
template: '<Foo />',
components: { 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: '<p>{{msg}}</p>',
})

const app = createApp(
defineComponent({
template: '<Foo />',
provide: {
msg: 'root component',
},
components: { Foo },
})
)
app.provide('msg', 'application')
const vm = app.mount()

await nextTick()
expect(vm.$el.textContent).toBe('root component')
})
})

0 comments on commit d167b9b

Please sign in to comment.