From fb06fcf8aba60b21b067ab5f8904d929683ab7a3 Mon Sep 17 00:00:00 2001 From: daiwei Date: Wed, 29 Oct 2025 16:56:28 +0800 Subject: [PATCH] chore: tweaks --- packages/runtime-dom/src/apiCustomElement.ts | 29 +++++++++++++------ .../src/apiDefineVaporCustomElement.ts | 10 +++---- packages/runtime-vapor/src/componentProps.ts | 2 +- ...ec.ts => ssr-custom-element-vapor.spec.ts} | 0 4 files changed, 26 insertions(+), 15 deletions(-) rename packages/vue/__tests__/e2e/{ssr-vapor-custom-element.spec.ts => ssr-custom-element-vapor.spec.ts} (100%) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 40d21ec0be..cf95eb4a80 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -220,7 +220,7 @@ export abstract class VueElementBase< /** * @internal */ - _root!: Element | ShadowRoot + _root: Element | ShadowRoot /** * @internal */ @@ -230,9 +230,6 @@ export abstract class VueElementBase< */ _teleportTargets?: Set - protected _def: Def - protected _props: Record - protected _createApp: CreateAppFunction protected _connected = false protected _resolved = false protected _numberProps: Record | null = null @@ -240,6 +237,10 @@ export abstract class VueElementBase< protected _pendingResolve: Promise | undefined protected _parent: VueElementBase | undefined + protected _def: Def + protected _props: Record + protected _createApp: CreateAppFunction + /** * dev only */ @@ -251,7 +252,12 @@ export abstract class VueElementBase< protected _ob?: MutationObserver | null = null protected _slots?: Record - protected abstract _hasPreRendered(): boolean | undefined + /** + * Check if this custom element needs hydration. + * Returns true if it has a pre-rendered declarative shadow root that + * needs to be hydrated. + */ + protected abstract _needsHydration(): boolean protected abstract _mount(def: Def): void protected abstract _update(): void protected abstract _unmount(): void @@ -272,7 +278,9 @@ export abstract class VueElementBase< this._createApp = createAppFn this._nonce = def.nonce - if (this._hasPreRendered()) { + if (this._needsHydration()) { + this._root = this.shadowRoot! + } else { if (def.shadowRoot !== false) { this.attachShadow( extend({}, def.shadowRootOptions, { @@ -439,6 +447,7 @@ export abstract class VueElementBase< private _mountComponent(def: Def): void { this._mount(def) + // apply expose after mount this._processExposed() } @@ -447,7 +456,9 @@ export abstract class VueElementBase< if (!exposed) return for (const key in exposed) { if (!hasOwn(this, key)) { + // exposed properties are readonly Object.defineProperty(this, key, { + // unwrap ref to be consistent with public instance behavior get: () => unref(exposed[key]), }) } else if (__DEV__) { @@ -723,9 +734,9 @@ export class VueElement extends VueElementBase< super(def, props, createAppFn) } - protected _hasPreRendered(): boolean | undefined { + protected _needsHydration(): boolean { if (this.shadowRoot && this._createApp !== createApp) { - this._root = this.shadowRoot + return true } else { if (__DEV__ && this.shadowRoot) { warn( @@ -733,8 +744,8 @@ export class VueElement extends VueElementBase< `defined as hydratable. Use \`defineSSRCustomElement\`.`, ) } - return true } + return false } protected _mount(def: InnerComponentDef): void { diff --git a/packages/runtime-vapor/src/apiDefineVaporCustomElement.ts b/packages/runtime-vapor/src/apiDefineVaporCustomElement.ts index 7624b66cee..f896b49eb5 100644 --- a/packages/runtime-vapor/src/apiDefineVaporCustomElement.ts +++ b/packages/runtime-vapor/src/apiDefineVaporCustomElement.ts @@ -70,9 +70,9 @@ export class VaporElement extends VueElementBase< super(def, props, createAppFn) } - protected _hasPreRendered(): boolean | undefined { + protected _needsHydration(): boolean { if (this.shadowRoot && this._createApp !== createVaporApp) { - this._root = this.shadowRoot + return true } else { if (__DEV__ && this.shadowRoot) { warn( @@ -80,8 +80,8 @@ export class VaporElement extends VueElementBase< `defined as hydratable. Use \`defineVaporSSRCustomElement\`.`, ) } - return true } + return false } protected _mount(def: VaporInnerComponentDef): void { if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && !def.name) { @@ -94,8 +94,8 @@ export class VaporElement extends VueElementBase< this._def.configureApp(this._app) } - // For SSR custom elements, we need to create component in hydration context - if (this._createApp === createVaporSSRApp) { + // create component in hydration context + if (this.shadowRoot && this._createApp === createVaporSSRApp) { withHydration(this._root, this._createComponent.bind(this)) } else { this._createComponent() diff --git a/packages/runtime-vapor/src/componentProps.ts b/packages/runtime-vapor/src/componentProps.ts index 496b001d3a..c10008b3af 100644 --- a/packages/runtime-vapor/src/componentProps.ts +++ b/packages/runtime-vapor/src/componentProps.ts @@ -97,7 +97,7 @@ export function getPropsProxyHandlers( return resolvePropValue( propsOptions!, key, - instance.type.ce ? rawProps[rawKey] : rawProps[rawKey](), + resolveSource(rawProps[rawKey]), instance, resolveDefault, ) diff --git a/packages/vue/__tests__/e2e/ssr-vapor-custom-element.spec.ts b/packages/vue/__tests__/e2e/ssr-custom-element-vapor.spec.ts similarity index 100% rename from packages/vue/__tests__/e2e/ssr-vapor-custom-element.spec.ts rename to packages/vue/__tests__/e2e/ssr-custom-element-vapor.spec.ts -- 2.47.3