]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(custom-element): reflect prop default value on custom element
authorEvan You <evan@vuejs.org>
Tue, 6 Aug 2024 18:51:29 +0000 (02:51 +0800)
committerEvan You <evan@vuejs.org>
Tue, 6 Aug 2024 18:51:29 +0000 (02:51 +0800)
close #9006
close #10537

packages/runtime-core/src/component.ts
packages/runtime-core/src/componentProps.ts
packages/runtime-dom/__tests__/customElement.spec.ts
packages/runtime-dom/src/apiCustomElement.ts

index f420a678a2faf3b9d555b6f7e768c8176d03e30f..8bff17b10398b1754378dcff984c3c1446636665 100644 (file)
@@ -1247,4 +1247,13 @@ export interface ComponentCustomElementInterface {
    * @internal
    */
   _removeChildStyle(type: ConcreteComponent): void
+  /**
+   * @internal
+   */
+  _setProp(
+    key: string,
+    val: any,
+    shouldReflect?: boolean,
+    shouldUpdate?: boolean,
+  ): void
 }
index 25431cf9f7464c82a20acd3ffcb9db4ef76e4a99..6b5b50a3ef6c6892517249343063361a85e71cfc 100644 (file)
@@ -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]) {
index 52e677ea625dd2484a42127550ad37c2fae4f98c..ffa7d28f8526c5808474b27b0844c3f2339e1406 100644 (file)
@@ -338,7 +338,7 @@ describe('defineCustomElement', () => {
       expect(el.shadowRoot!.innerHTML).toMatchInlineSnapshot('"<div>foo</div>"')
     })
 
-    // # 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 = `<my-el-default-val></my-el-default-val>`
+      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 => {
index 6af68193a0894ac6d852c072a2f5f20b4187f69c..306d2edf698ec790850bc9deabb2277b6c30db8d 100644 (file)
@@ -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) {