Skip to content

Commit 4b8a7fb

Browse files
committed
wip: save
1 parent da010a7 commit 4b8a7fb

File tree

5 files changed

+137
-63
lines changed

5 files changed

+137
-63
lines changed

packages/runtime-core/src/apiCreateApp.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ export interface App<HostElement = any> {
111111
*/
112112
_ceVNode?: VNode
113113

114+
/**
115+
* @internal vapor custom element instance
116+
*/
117+
_ceComponent?: GenericComponentInstance | null
118+
114119
/**
115120
* v2 compat only
116121
*/

packages/runtime-dom/src/apiCustomElement.ts

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ export abstract class VueElementBase<
252252
protected _slots?: Record<string, Node[]>
253253

254254
protected abstract _hasPreRendered(): boolean | undefined
255-
protected abstract _mountComponent(def: Def): void
256-
protected abstract _updateComponent(): void
257-
protected abstract _unmountComponent(): void
255+
protected abstract _mount(def: Def): void
256+
protected abstract _update(): void
257+
protected abstract _unmount(): void
258258

259259
constructor(
260260
/**
@@ -352,7 +352,7 @@ export abstract class VueElementBase<
352352
this._ob.disconnect()
353353
this._ob = null
354354
}
355-
this._unmountComponent()
355+
this._unmount()
356356
if (this._teleportTargets) {
357357
this._teleportTargets.clear()
358358
this._teleportTargets = undefined
@@ -436,6 +436,45 @@ export abstract class VueElementBase<
436436
}
437437
}
438438

439+
private _mountComponent(def: Def): void {
440+
this._mount(def)
441+
this._processExposed()
442+
}
443+
444+
protected _processExposed(): void {
445+
const exposed = this._instance && this._instance.exposed
446+
if (!exposed) return
447+
for (const key in exposed) {
448+
if (!hasOwn(this, key)) {
449+
Object.defineProperty(this, key, {
450+
get: () => unref(exposed[key]),
451+
})
452+
} else if (__DEV__) {
453+
warn(`Exposed property "${key}" already exists on custom element.`)
454+
}
455+
}
456+
}
457+
458+
protected _processEmit(): void {
459+
const dispatch = (event: string, args: any[]) => {
460+
this.dispatchEvent(
461+
new CustomEvent(
462+
event,
463+
isPlainObject(args[0])
464+
? extend({ detail: args }, args[0])
465+
: { detail: args },
466+
),
467+
)
468+
}
469+
470+
this._instance!.emit = (event: string, ...args: any[]) => {
471+
dispatch(event, args)
472+
if (hyphenate(event) !== event) {
473+
dispatch(hyphenate(event), args)
474+
}
475+
}
476+
}
477+
439478
private _resolveProps(def: Def): void {
440479
const { props } = def
441480
const declaredPropKeys = isArray(props) ? props : Object.keys(props || {})
@@ -498,7 +537,7 @@ export abstract class VueElementBase<
498537
}
499538
}
500539
if (shouldUpdate && this._instance) {
501-
this._updateComponent()
540+
this._update()
502541
}
503542
// reflect
504543
if (shouldReflect) {
@@ -666,7 +705,7 @@ export class VueElement extends VueElementBase<
666705
}
667706
}
668707

669-
protected _mountComponent(def: InnerComponentDef): void {
708+
protected _mount(def: InnerComponentDef): void {
670709
if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && !def.name) {
671710
// @ts-expect-error
672711
def.name = 'VueElement'
@@ -678,28 +717,16 @@ export class VueElement extends VueElementBase<
678717
}
679718
this._app._ceVNode = this._createVNode()
680719
this._app.mount(this._root)
681-
682-
const exposed = this._instance && this._instance.exposed
683-
if (!exposed) return
684-
for (const key in exposed) {
685-
if (!hasOwn(this, key)) {
686-
Object.defineProperty(this, key, {
687-
get: () => unref(exposed[key]),
688-
})
689-
} else if (__DEV__) {
690-
warn(`Exposed property "${key}" already exists on custom element.`)
691-
}
692-
}
693720
}
694721

695-
protected _updateComponent(): void {
722+
protected _update(): void {
696723
if (!this._app) return
697724
const vnode = this._createVNode()
698725
vnode.appContext = this._app._context
699726
render(vnode, this._root)
700727
}
701728

702-
protected _unmountComponent(): void {
729+
protected _unmount(): void {
703730
if (this._app) {
704731
this._app.unmount()
705732
}
@@ -729,28 +756,11 @@ export class VueElement extends VueElementBase<
729756
}
730757
this._applyStyles(newStyles)
731758
this._instance = null
732-
this._updateComponent()
733-
}
734-
}
735-
736-
const dispatch = (event: string, args: any[]) => {
737-
this.dispatchEvent(
738-
new CustomEvent(
739-
event,
740-
isPlainObject(args[0])
741-
? extend({ detail: args }, args[0])
742-
: { detail: args },
743-
),
744-
)
745-
}
746-
747-
instance.emit = (event: string, ...args: any[]) => {
748-
dispatch(event, args)
749-
if (hyphenate(event) !== event) {
750-
dispatch(hyphenate(event), args)
759+
this._update()
751760
}
752761
}
753762

763+
this._processEmit()
754764
this._setParent()
755765
}
756766
}

packages/runtime-vapor/src/apiCreateApp.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@ const mountApp: AppMountFn<ParentNode> = (app, container) => {
3636
container.textContent = ''
3737
}
3838

39-
const instance = createComponent(
40-
app._component,
41-
app._props as RawProps,
42-
null,
43-
false,
44-
false,
45-
app._context,
46-
)
39+
const instance =
40+
(app._ceComponent as VaporComponentInstance) ||
41+
createComponent(
42+
app._component,
43+
app._props as RawProps,
44+
null,
45+
false,
46+
false,
47+
app._context,
48+
)
4749
mountComponent(instance, container)
4850
flushOnAppMount()
4951

@@ -57,14 +59,16 @@ const hydrateApp: AppMountFn<ParentNode> = (app, container) => {
5759

5860
let instance: VaporComponentInstance
5961
withHydration(container, () => {
60-
instance = createComponent(
61-
app._component,
62-
app._props as RawProps,
63-
null,
64-
false,
65-
false,
66-
app._context,
67-
)
62+
instance =
63+
(app._ceComponent as VaporComponentInstance) ||
64+
createComponent(
65+
app._component,
66+
app._props as RawProps,
67+
null,
68+
false,
69+
false,
70+
app._context,
71+
)
6872
mountComponent(instance, container)
6973
flushOnAppMount()
7074
})

packages/runtime-vapor/src/apiDefineVaporCustomElement.ts

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import { extend, isPlainObject } from '@vue/shared'
2-
import { createVaporApp, defineVaporComponent } from '.'
2+
import { createComponent, createVaporApp, defineVaporComponent } from '.'
33
import {
44
type CreateAppFunction,
55
type CustomElementOptions,
66
VueElementBase,
77
warn,
88
} from '@vue/runtime-dom'
9-
import type { ObjectVaporComponent, VaporComponent } from './component'
9+
import {
10+
type ObjectVaporComponent,
11+
type VaporComponent,
12+
type VaporComponentInstance,
13+
mountComponent,
14+
unmountComponent,
15+
} from './component'
1016

1117
export type VaporElementConstructor<P = {}> = {
1218
new (initialProps?: Record<string, any>): VaporElement & P
@@ -72,13 +78,58 @@ export class VaporElement extends VueElementBase<
7278
return true
7379
}
7480
}
75-
protected _mountComponent(def: VaporInnerComponentDef): void {
76-
throw new Error('Method not implemented.')
81+
protected _mount(def: VaporInnerComponentDef): void {
82+
if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && !def.name) {
83+
def.name = 'VaporElement'
84+
}
85+
86+
this._app = this._createApp(this._def)
87+
this._inheritParentContext()
88+
if (this._def.configureApp) {
89+
this._def.configureApp(this._app)
90+
}
91+
92+
this._app._ceComponent = this._createComponent()
93+
this._app!.mount(this._root)
94+
}
95+
96+
protected _update(): void {
97+
if (!this._app) return
98+
unmountComponent(this._instance! as VaporComponentInstance, this._root)
99+
const instance = this._createComponent()
100+
instance.appContext = this._app!._context
101+
mountComponent(this._instance! as VaporComponentInstance, this._root)
77102
}
78-
protected _updateComponent(): void {
79-
throw new Error('Method not implemented.')
103+
104+
protected _unmount(): void {
105+
this._app!.unmount()
106+
this._app = this._instance = null
80107
}
81-
protected _unmountComponent(): void {
82-
throw new Error('Method not implemented.')
108+
109+
private _createComponent() {
110+
this._instance = createComponent(this._def, this._props)
111+
if (!this.shadowRoot) {
112+
this._instance!.m = this._instance!.u = [this._renderSlots.bind(this)]
113+
}
114+
115+
this._instance.ce = this
116+
this._instance.isCE = true
117+
118+
if (__DEV__) {
119+
this._instance.ceReload = newStyles => {
120+
if (this._styles) {
121+
this._styles.forEach(s => this._root.removeChild(s))
122+
this._styles.length = 0
123+
}
124+
this._applyStyles(newStyles)
125+
this._instance = null
126+
this._update()
127+
}
128+
}
129+
130+
this._processEmit()
131+
this._setParent()
132+
133+
return this._instance
83134
}
84135
}

packages/runtime-vapor/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ export { vaporInteropPlugin } from './vdomInterop'
66
export type { VaporDirective } from './directives/custom'
77
export { VaporTeleportImpl as VaporTeleport } from './components/Teleport'
88
export { VaporKeepAliveImpl as VaporKeepAlive } from './components/KeepAlive'
9+
export {
10+
defineVaporCustomElement,
11+
defineVaporSSRCustomElement,
12+
} from './apiDefineVaporCustomElement'
913

1014
// compiler-use only
1115
export { insert, prepend, remove } from './block'

0 commit comments

Comments
 (0)