Przeglądaj źródła

fix(custom-element): reflect prop default value on custom element

close #9006
close #10537
Evan You 1 rok temu
rodzic
commit
63689ed776

+ 9 - 0
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
 }

+ 4 - 0
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]) {

+ 20 - 1
packages/runtime-dom/__tests__/customElement.spec.ts

@@ -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 => {

+ 4 - 9
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) {