/
createApp.ts
76 lines (71 loc) · 2.21 KB
/
createApp.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import type Vue from 'vue'
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> {
config: VueConstructor['config']
use: VueConstructor['use']
mixin: VueConstructor['mixin']
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']
}
export function createApp(rootComponent: any, rootProps: any = undefined): App {
const V = getVueConstructor()!
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)
return app
} else {
return V.directive(name)
}
},
mount: (el, hydrating) => {
if (!mountedVM) {
mountedVM = new V({
propsData: rootProps,
...rootComponent,
provide: { ...provide, ...rootComponent.provide },
})
mountedVM.$mount(el, hydrating)
return mountedVM
} else {
if (__DEV__) {
warn(
`App has already been mounted.\n` +
`If you want to remount the same app, move your app creation logic ` +
`into a factory function and create fresh app instances for each ` +
`mount - e.g. \`const createMyApp = () => createApp(App)\``
)
}
return mountedVM
}
},
unmount: () => {
if (mountedVM) {
mountedVM.$destroy()
mountedVM = undefined
} else if (__DEV__) {
warn(`Cannot unmount an app that is not mounted.`)
}
},
}
return app
}