Skip to content

Commit fd9b50b

Browse files
committed
feat(runtime-vapor): app.component()
1 parent d77c7ad commit fd9b50b

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

packages/runtime-vapor/src/apiCreateVaporApp.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { isFunction, isObject } from '@vue/shared'
1+
import { NO, isFunction, isObject } from '@vue/shared'
22
import {
33
type Component,
44
type ComponentInternalInstance,
55
createComponentInstance,
6+
validateComponentName,
67
} from './component'
78
import { warn } from './warning'
89
import { version } from '.'
@@ -60,6 +61,20 @@ export function createVaporApp(
6061
return app
6162
},
6263

64+
component(name: string, component?: Component): any {
65+
if (__DEV__) {
66+
validateComponentName(name, context.config)
67+
}
68+
if (!component) {
69+
return context.components[name]
70+
}
71+
if (__DEV__ && context.components[name]) {
72+
warn(`Component "${name}" has already been registered in target app.`)
73+
}
74+
context.components[name] = component
75+
return app
76+
},
77+
6378
mount(rootContainer): any {
6479
if (!instance) {
6580
instance = createComponentInstance(
@@ -119,10 +134,12 @@ export function createAppContext(): AppContext {
119134
return {
120135
app: null as any,
121136
config: {
137+
isNativeTag: NO,
122138
errorHandler: undefined,
123139
warnHandler: undefined,
124140
globalProperties: {},
125141
},
142+
components: {},
126143
provides: Object.create(null),
127144
}
128145
}
@@ -151,6 +168,11 @@ export interface App {
151168
): this
152169
use<Options>(plugin: Plugin<Options>, options: Options): this
153170

171+
component(name: string): Component | undefined
172+
// TODO: DefineComponent
173+
// component<T extends Component | DefineComponent>(
174+
component<T extends Component>(name: string, component: T): this
175+
154176
mount(
155177
rootContainer: ParentNode | string,
156178
isHydrate?: boolean,
@@ -163,6 +185,9 @@ export interface App {
163185
}
164186

165187
export interface AppConfig {
188+
// @private
189+
readonly isNativeTag: (tag: string) => boolean
190+
166191
errorHandler?: (
167192
err: unknown,
168193
instance: ComponentInternalInstance | null,
@@ -179,6 +204,7 @@ export interface AppConfig {
179204
export interface AppContext {
180205
app: App // for devtools
181206
config: AppConfig
207+
components: Record<string, Component>
182208
provides: Record<string | symbol, any>
183209
}
184210

packages/runtime-vapor/src/component.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { EffectScope, isRef } from '@vue/reactivity'
2-
import { EMPTY_OBJ, hasOwn, isArray, isFunction } from '@vue/shared'
2+
import { EMPTY_OBJ, hasOwn, isArray, isFunction, makeMap } from '@vue/shared'
33
import type { Block } from './apiRender'
44
import type { DirectiveBinding } from './directives'
55
import {
@@ -25,7 +25,11 @@ import {
2525
} from './componentSlots'
2626
import { VaporLifecycleHooks } from './apiLifecycle'
2727
import { warn } from './warning'
28-
import { type AppContext, createAppContext } from './apiCreateVaporApp'
28+
import {
29+
type AppConfig,
30+
type AppContext,
31+
createAppContext,
32+
} from './apiCreateVaporApp'
2933
import type { Data } from '@vue/runtime-shared'
3034

3135
export type Component = FunctionalComponent | ObjectComponent
@@ -362,6 +366,19 @@ export function createComponentInstance(
362366
return instance
363367
}
364368

369+
const isBuiltInTag = /*#__PURE__*/ makeMap('slot,component')
370+
371+
export function validateComponentName(
372+
name: string,
373+
{ isNativeTag }: AppConfig,
374+
) {
375+
if (isBuiltInTag(name) || isNativeTag(name)) {
376+
warn(
377+
'Do not use built-in or reserved HTML elements as component id: ' + name,
378+
)
379+
}
380+
}
381+
365382
export function isVaporComponent(
366383
val: unknown,
367384
): val is ComponentInternalInstance {

0 commit comments

Comments
 (0)