]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(custom-element): avoid triggering mutationObserver when relecting props
authorEvan You <evan@vuejs.org>
Fri, 15 Nov 2024 09:20:59 +0000 (17:20 +0800)
committerEvan You <evan@vuejs.org>
Fri, 15 Nov 2024 09:21:49 +0000 (17:21 +0800)
close #12214
close #12215

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

index 6b9f7d1391e3a3c10f604e7134f89b5a00c7e63d..df438d47eeeadabc0854871d233ea241b2e48021 100644 (file)
@@ -396,6 +396,38 @@ describe('defineCustomElement', () => {
       expect(e.value).toBe('hi')
     })
 
+    // #12214
+    test('Boolean prop with default true', async () => {
+      const E = defineCustomElement({
+        props: {
+          foo: {
+            type: Boolean,
+            default: true,
+          },
+        },
+        render() {
+          return String(this.foo)
+        },
+      })
+      customElements.define('my-el-default-true', E)
+      container.innerHTML = `<my-el-default-true></my-el-default-true>`
+      const e = container.childNodes[0] as HTMLElement & { foo: any },
+        shadowRoot = e.shadowRoot as ShadowRoot
+      expect(shadowRoot.innerHTML).toBe('true')
+      e.foo = undefined
+      await nextTick()
+      expect(shadowRoot.innerHTML).toBe('true')
+      e.foo = false
+      await nextTick()
+      expect(shadowRoot.innerHTML).toBe('false')
+      e.foo = null
+      await nextTick()
+      expect(shadowRoot.innerHTML).toBe('null')
+      e.foo = ''
+      await nextTick()
+      expect(shadowRoot.innerHTML).toBe('true')
+    })
+
     test('support direct setup function syntax with extra options', () => {
       const E = defineCustomElement(
         props => {
index 6ddaf89713016db4582689ec2c2dec0cd349b21e..aeeaeec9b9f8445869107370666010ede7761526 100644 (file)
@@ -505,6 +505,8 @@ export class VueElement
       }
       // reflect
       if (shouldReflect) {
+        const ob = this._ob
+        ob && ob.disconnect()
         if (val === true) {
           this.setAttribute(hyphenate(key), '')
         } else if (typeof val === 'string' || typeof val === 'number') {
@@ -512,6 +514,7 @@ export class VueElement
         } else if (!val) {
           this.removeAttribute(hyphenate(key))
         }
+        ob && ob.observe(this, { attributes: true })
       }
     }
   }