Skip to content

Commit da010a7

Browse files
committed
wip: enhance VaporElement with type parameters and pre-rendering support
1 parent e808152 commit da010a7

File tree

2 files changed

+79
-22
lines changed

2 files changed

+79
-22
lines changed

packages/runtime-dom/src/apiCustomElement.ts

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ const BaseClass = (
201201
type InnerComponentDef = ConcreteComponent & CustomElementOptions
202202

203203
export abstract class VueElementBase<
204+
E = Element,
205+
C = Component,
204206
Def extends CustomElementOptions & { props?: any } = InnerComponentDef,
205207
>
206208
extends BaseClass
@@ -218,7 +220,7 @@ export abstract class VueElementBase<
218220
/**
219221
* @internal
220222
*/
221-
_root: Element | ShadowRoot
223+
_root!: Element | ShadowRoot
222224
/**
223225
* @internal
224226
*/
@@ -230,7 +232,7 @@ export abstract class VueElementBase<
230232

231233
protected _def: Def
232234
protected _props: Record<string, any>
233-
protected _createApp: CreateAppFunction<Element>
235+
protected _createApp: CreateAppFunction<E, C>
234236
protected _connected = false
235237
protected _resolved = false
236238
protected _numberProps: Record<string, true> | null = null
@@ -249,29 +251,27 @@ export abstract class VueElementBase<
249251
protected _ob?: MutationObserver | null = null
250252
protected _slots?: Record<string, Node[]>
251253

254+
protected abstract _hasPreRendered(): boolean | undefined
255+
protected abstract _mountComponent(def: Def): void
256+
protected abstract _updateComponent(): void
257+
protected abstract _unmountComponent(): void
258+
252259
constructor(
253260
/**
254261
* Component def - note this may be an AsyncWrapper, and this._def will
255262
* be overwritten by the inner component when resolved.
256263
*/
257264
def: Def,
258-
props: Record<string, any> = {},
259-
createAppFn: CreateAppFunction<Element> = createApp,
265+
props: Record<string, any> | undefined = {},
266+
createAppFn: CreateAppFunction<E, C>,
260267
) {
261268
super()
262269
this._def = def
263270
this._props = props
264271
this._createApp = createAppFn
265272
this._nonce = def.nonce
266-
if (this.shadowRoot && createAppFn !== createApp) {
267-
this._root = this.shadowRoot
268-
} else {
269-
if (__DEV__ && this.shadowRoot) {
270-
warn(
271-
`Custom element has pre-rendered declarative shadow root but is not ` +
272-
`defined as hydratable. Use \`defineSSRCustomElement\`.`,
273-
)
274-
}
273+
274+
if (this._hasPreRendered()) {
275275
if (def.shadowRoot !== false) {
276276
this.attachShadow(
277277
extend({}, def.shadowRootOptions, {
@@ -322,10 +322,6 @@ export abstract class VueElementBase<
322322
}
323323
}
324324

325-
protected abstract _mountComponent(def: Def): void
326-
protected abstract _updateComponent(): void
327-
protected abstract _unmountComponent(): void
328-
329325
protected _setParent(
330326
parent: VueElementBase | undefined = this._parent,
331327
): void {
@@ -643,7 +639,33 @@ export abstract class VueElementBase<
643639
}
644640
}
645641

646-
export class VueElement extends VueElementBase<InnerComponentDef> {
642+
export class VueElement extends VueElementBase<
643+
Element,
644+
Component,
645+
InnerComponentDef
646+
> {
647+
constructor(
648+
def: InnerComponentDef,
649+
props: Record<string, any> | undefined = {},
650+
createAppFn: CreateAppFunction<Element, Component> = createApp,
651+
) {
652+
super(def, props, createAppFn)
653+
}
654+
655+
protected _hasPreRendered(): boolean | undefined {
656+
if (this.shadowRoot && this._createApp !== createApp) {
657+
this._root = this.shadowRoot
658+
} else {
659+
if (__DEV__ && this.shadowRoot) {
660+
warn(
661+
`Custom element has pre-rendered declarative shadow root but is not ` +
662+
`defined as hydratable. Use \`defineSSRCustomElement\`.`,
663+
)
664+
}
665+
return true
666+
}
667+
}
668+
647669
protected _mountComponent(def: InnerComponentDef): void {
648670
if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && !def.name) {
649671
// @ts-expect-error

packages/runtime-vapor/src/apiDefineVaporCustomElement.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { extend, isPlainObject } from '@vue/shared'
2-
import { defineVaporComponent } from '.'
2+
import { createVaporApp, defineVaporComponent } from '.'
33
import {
44
type CreateAppFunction,
55
type CustomElementOptions,
66
VueElementBase,
7+
warn,
78
} from '@vue/runtime-dom'
89
import type { ObjectVaporComponent, VaporComponent } from './component'
910

@@ -14,13 +15,13 @@ export type VaporElementConstructor<P = {}> = {
1415
// TODO type inference
1516

1617
/*@__NO_SIDE_EFFECTS__*/
17-
export function defineCustomElement(
18+
export function defineVaporCustomElement(
1819
options: any,
1920
extraOptions?: Omit<ObjectVaporComponent, 'setup'>,
2021
/**
2122
* @internal
2223
*/
23-
_createApp?: CreateAppFunction<Element>,
24+
_createApp?: CreateAppFunction<ParentNode, VaporComponent>,
2425
): VaporElementConstructor {
2526
let Comp = defineVaporComponent(options, extraOptions)
2627
if (isPlainObject(Comp)) Comp = extend({}, Comp, extraOptions)
@@ -34,9 +35,43 @@ export function defineCustomElement(
3435
return VaporCustomElement
3536
}
3637

38+
/*@__NO_SIDE_EFFECTS__*/
39+
export const defineVaporSSRCustomElement = ((
40+
options: any,
41+
extraOptions?: Omit<ObjectVaporComponent, 'setup'>,
42+
) => {
43+
// @ts-expect-error
44+
return defineVaporCustomElement(options, extraOptions, createVaporSSRApp)
45+
}) as typeof defineVaporCustomElement
46+
3747
type VaporInnerComponentDef = VaporComponent & CustomElementOptions
3848

39-
export class VaporElement extends VueElementBase<VaporInnerComponentDef> {
49+
export class VaporElement extends VueElementBase<
50+
ParentNode,
51+
VaporComponent,
52+
VaporInnerComponentDef
53+
> {
54+
constructor(
55+
def: VaporInnerComponentDef,
56+
props: Record<string, any> | undefined = {},
57+
createAppFn: CreateAppFunction<ParentNode, VaporComponent> = createVaporApp,
58+
) {
59+
super(def, props, createAppFn)
60+
}
61+
62+
protected _hasPreRendered(): boolean | undefined {
63+
if (this.shadowRoot && this._createApp !== createVaporApp) {
64+
this._root = this.shadowRoot
65+
} else {
66+
if (__DEV__ && this.shadowRoot) {
67+
warn(
68+
`Custom element has pre-rendered declarative shadow root but is not ` +
69+
`defined as hydratable. Use \`defineVaporSSRCustomElement\`.`,
70+
)
71+
}
72+
return true
73+
}
74+
}
4075
protected _mountComponent(def: VaporInnerComponentDef): void {
4176
throw new Error('Method not implemented.')
4277
}

0 commit comments

Comments
 (0)