]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(custom-element): delete prop on attribute removal
authorEvan You <evan@vuejs.org>
Thu, 8 Aug 2024 10:37:54 +0000 (18:37 +0800)
committerEvan You <evan@vuejs.org>
Thu, 8 Aug 2024 10:37:54 +0000 (18:37 +0800)
close #11276

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

index da0d614f6574cd77369f5982de1f177499c97da6..ac66230e32b9ef9171a33452b0fb6aef5ad059be 100644 (file)
@@ -1241,4 +1241,25 @@ describe('defineCustomElement', () => {
     expect(e.shadowRoot!.innerHTML).toBe(`<div>fooValue</div>`)
     app.unmount()
   })
+
+  // #11276
+  test('delete prop on attr removal', async () => {
+    const E = defineCustomElement({
+      props: {
+        boo: {
+          type: Boolean,
+        },
+      },
+      render() {
+        return this.boo + ',' + typeof this.boo
+      },
+    })
+    customElements.define('el-attr-removal', E)
+    container.innerHTML = '<el-attr-removal boo>'
+    const e = container.childNodes[0] as VueElement
+    expect(e.shadowRoot!.innerHTML).toBe(`true,boolean`)
+    e.removeAttribute('boo')
+    await nextTick()
+    expect(e.shadowRoot!.innerHTML).toBe(`false,boolean`)
+  })
 })
index aa191ba6c7ced1965d5adc196cc1643e14af4420..fe0e4d90b7a4c1b77ee6f47a48161864fa7c3d62 100644 (file)
@@ -42,6 +42,9 @@ import {
 } from '@vue/shared'
 import { createApp, createSSRApp, render } from '.'
 
+// marker for attr removal
+const REMOVAL = {}
+
 export type VueElementConstructor<P = {}> = {
   new (initialProps?: Record<string, any>): VueElement & P
 }
@@ -455,9 +458,10 @@ export class VueElement
 
   protected _setAttr(key: string) {
     if (key.startsWith('data-v-')) return
-    let value = this.hasAttribute(key) ? this.getAttribute(key) : undefined
+    const has = this.hasAttribute(key)
+    let value = has ? this.getAttribute(key) : REMOVAL
     const camelKey = camelize(key)
-    if (this._numberProps && this._numberProps[camelKey]) {
+    if (has && this._numberProps && this._numberProps[camelKey]) {
       value = toNumber(value)
     }
     this._setProp(camelKey, value, false, true)
@@ -475,7 +479,11 @@ export class VueElement
    */
   _setProp(key: string, val: any, shouldReflect = true, shouldUpdate = false) {
     if (val !== this._props[key]) {
-      this._props[key] = val
+      if (val === REMOVAL) {
+        delete this._props[key]
+      } else {
+        this._props[key] = val
+      }
       if (shouldUpdate && this._instance) {
         this._update()
       }