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) {