diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index f420a678a2f..8bff17b1039 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -1247,4 +1247,13 @@ export interface ComponentCustomElementInterface { * @internal */ _removeChildStyle(type: ConcreteComponent): void + /** + * @internal + */ + _setProp( + key: string, + val: any, + shouldReflect?: boolean, + shouldUpdate?: boolean, + ): void } diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index 25431cf9f74..6b5b50a3ef6 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -480,6 +480,10 @@ function resolvePropValue( } else { value = defaultValue } + // #9006 reflect default value on custom element + if (instance.ce) { + instance.ce._setProp(key, value) + } } // boolean casting if (opt[BooleanFlags.shouldCast]) { diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 52e677ea625..ffa7d28f852 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -338,7 +338,7 @@ describe('defineCustomElement', () => { expect(el.shadowRoot!.innerHTML).toMatchInlineSnapshot('"
foo
"') }) - // # 5793 + // #5793 test('set number value in dom property', () => { const E = defineCustomElement({ props: { @@ -357,6 +357,25 @@ describe('defineCustomElement', () => { expect(el.shadowRoot.innerHTML).toBe('max age: 50/type: number') }) + // #9006 + test('should reflect default value', () => { + const E = defineCustomElement({ + props: { + value: { + type: String, + default: 'hi', + }, + }, + render() { + return this.value + }, + }) + customElements.define('my-el-default-val', E) + container.innerHTML = `` + const e = container.childNodes[0] as any + expect(e.value).toBe('hi') + }) + test('support direct setup function syntax with extra options', () => { const E = defineCustomElement( props => { diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 6af68193a08..306d2edf698 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -395,7 +395,7 @@ export class VueElement // check if there are props set pre-upgrade or connect for (const key of Object.keys(this)) { if (key[0] !== '_' && declaredPropKeys.includes(key)) { - this._setProp(key, this[key as keyof this], true, false) + this._setProp(key, this[key as keyof this]) } } @@ -406,7 +406,7 @@ export class VueElement return this._getProp(key) }, set(val) { - this._setProp(key, val) + this._setProp(key, val, true, true) }, }) } @@ -435,7 +435,7 @@ export class VueElement if (this._numberProps && this._numberProps[camelKey]) { value = toNumber(value) } - this._setProp(camelKey, value, false) + this._setProp(camelKey, value, false, true) } /** @@ -448,12 +448,7 @@ export class VueElement /** * @internal */ - protected _setProp( - key: string, - val: any, - shouldReflect = true, - shouldUpdate = true, - ) { + _setProp(key: string, val: any, shouldReflect = true, shouldUpdate = false) { if (val !== this._props[key]) { this._props[key] = val if (shouldUpdate && this._instance) {