mirror of https://github.com/vuejs/core.git
feat(runtime-vapor): implement app plugin
This commit is contained in:
parent
b776f92596
commit
d77c7ade77
|
@ -0,0 +1,45 @@
|
|||
import { type Component, type Plugin, createVaporApp, inject } from '../src'
|
||||
;``
|
||||
describe('api: createApp', () => {
|
||||
test('use', () => {
|
||||
const PluginA: Plugin = app => app.provide('foo', 1)
|
||||
const PluginB: Plugin = {
|
||||
install: (app, arg1, arg2) => app.provide('bar', arg1 + arg2),
|
||||
}
|
||||
class PluginC {
|
||||
someProperty = {}
|
||||
static install() {
|
||||
app.provide('baz', 2)
|
||||
}
|
||||
}
|
||||
const PluginD: any = undefined
|
||||
|
||||
const Root: Component = {
|
||||
setup() {
|
||||
const foo = inject('foo')
|
||||
const bar = inject('bar')
|
||||
return document.createTextNode(`${foo},${bar}`)
|
||||
},
|
||||
}
|
||||
|
||||
const app = createVaporApp(Root)
|
||||
app.use(PluginA)
|
||||
app.use(PluginB, 1, 1)
|
||||
app.use(PluginC)
|
||||
|
||||
const root = document.createElement('div')
|
||||
app.mount(root)
|
||||
expect(root.innerHTML).toBe(`1,2`)
|
||||
|
||||
app.use(PluginA)
|
||||
expect(
|
||||
`Plugin has already been applied to target app`,
|
||||
).toHaveBeenWarnedTimes(1)
|
||||
|
||||
app.use(PluginD)
|
||||
expect(
|
||||
`A plugin must either be a function or an object with an "install" ` +
|
||||
`function.`,
|
||||
).toHaveBeenWarnedTimes(1)
|
||||
})
|
||||
})
|
|
@ -21,6 +21,8 @@ export function createVaporApp(
|
|||
}
|
||||
|
||||
const context = createAppContext()
|
||||
const installedPlugins = new WeakSet()
|
||||
|
||||
let instance: ComponentInternalInstance
|
||||
|
||||
const app: App = {
|
||||
|
@ -40,6 +42,24 @@ export function createVaporApp(
|
|||
}
|
||||
},
|
||||
|
||||
use(plugin: Plugin, ...options: any[]) {
|
||||
if (installedPlugins.has(plugin)) {
|
||||
__DEV__ && warn(`Plugin has already been applied to target app.`)
|
||||
} else if (plugin && isFunction(plugin.install)) {
|
||||
installedPlugins.add(plugin)
|
||||
plugin.install(app, ...options)
|
||||
} else if (isFunction(plugin)) {
|
||||
installedPlugins.add(plugin)
|
||||
plugin(app, ...options)
|
||||
} else if (__DEV__) {
|
||||
warn(
|
||||
`A plugin must either be a function or an object with an "install" ` +
|
||||
`function.`,
|
||||
)
|
||||
}
|
||||
return app
|
||||
},
|
||||
|
||||
mount(rootContainer): any {
|
||||
if (!instance) {
|
||||
instance = createComponentInstance(
|
||||
|
@ -107,10 +127,30 @@ export function createAppContext(): AppContext {
|
|||
}
|
||||
}
|
||||
|
||||
type PluginInstallFunction<Options = any[]> = Options extends unknown[]
|
||||
? (app: App, ...options: Options) => any
|
||||
: (app: App, options: Options) => any
|
||||
|
||||
export type ObjectPlugin<Options = any[]> = {
|
||||
install: PluginInstallFunction<Options>
|
||||
}
|
||||
export type FunctionPlugin<Options = any[]> = PluginInstallFunction<Options> &
|
||||
Partial<ObjectPlugin<Options>>
|
||||
|
||||
export type Plugin<Options = any[]> =
|
||||
| FunctionPlugin<Options>
|
||||
| ObjectPlugin<Options>
|
||||
|
||||
export interface App {
|
||||
version: string
|
||||
config: AppConfig
|
||||
|
||||
use<Options extends unknown[]>(
|
||||
plugin: Plugin<Options>,
|
||||
...options: Options
|
||||
): this
|
||||
use<Options>(plugin: Plugin<Options>, options: Options): this
|
||||
|
||||
mount(
|
||||
rootContainer: ParentNode | string,
|
||||
isHydrate?: boolean,
|
||||
|
|
|
@ -121,6 +121,9 @@ export {
|
|||
type App,
|
||||
type AppConfig,
|
||||
type AppContext,
|
||||
type Plugin,
|
||||
type ObjectPlugin,
|
||||
type FunctionPlugin,
|
||||
} from './apiCreateVaporApp'
|
||||
export { createIf } from './apiCreateIf'
|
||||
export { createFor } from './apiCreateFor'
|
||||
|
|
Loading…
Reference in New Issue