]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(custom-element): properly remove hyphenated attribute (#12143)
authoredison <daiwei521@126.com>
Fri, 11 Oct 2024 01:52:06 +0000 (09:52 +0800)
committerGitHub <noreply@github.com>
Fri, 11 Oct 2024 01:52:06 +0000 (09:52 +0800)
close #12139

packages/runtime-dom/__tests__/customElement.spec.ts
packages/runtime-dom/src/modules/props.ts
packages/runtime-dom/src/patchProp.ts

index ef5051f42f7567fe63973c13b62fbf0eeb132b3b..6b9f7d1391e3a3c10f604e7134f89b5a00c7e63d 100644 (file)
@@ -1386,4 +1386,39 @@ describe('defineCustomElement', () => {
     await nextTick()
     expect(e.shadowRoot!.innerHTML).toBe(`false,boolean`)
   })
+
+  test('hyphenated attr removal', async () => {
+    const E = defineCustomElement({
+      props: {
+        fooBar: {
+          type: Boolean,
+        },
+      },
+      render() {
+        return this.fooBar
+      },
+    })
+    customElements.define('el-hyphenated-attr-removal', E)
+    const toggle = ref(true)
+    const Comp = {
+      render() {
+        return h('el-hyphenated-attr-removal', {
+          'foo-bar': toggle.value ? '' : null,
+        })
+      },
+    }
+    render(h(Comp), container)
+    const el = container.children[0]
+    expect(el.hasAttribute('foo-bar')).toBe(true)
+    expect((el as any).outerHTML).toBe(
+      `<el-hyphenated-attr-removal foo-bar=""></el-hyphenated-attr-removal>`,
+    )
+
+    toggle.value = false
+    await nextTick()
+    expect(el.hasAttribute('foo-bar')).toBe(false)
+    expect((el as any).outerHTML).toBe(
+      `<el-hyphenated-attr-removal></el-hyphenated-attr-removal>`,
+    )
+  })
 })
index 93d45c9e1607f85da3fe37e2d160a716fed6a60f..98608831a9a650a388dc994006269d254cacdb8c 100644 (file)
@@ -8,6 +8,7 @@ export function patchDOMProp(
   key: string,
   value: any,
   parentComponent: any,
+  attrName?: string,
 ): void {
   // __UNSAFE__
   // Reason: potentially setting innerHTML.
@@ -106,5 +107,5 @@ export function patchDOMProp(
       )
     }
   }
-  needRemove && el.removeAttribute(key)
+  needRemove && el.removeAttribute(attrName || key)
 }
index 5814e77c4f820d6288ea8213bcce9dee4b3b9715..b6af8997112ba533c62979b47fb1526890261817 100644 (file)
@@ -62,7 +62,7 @@ export const patchProp: DOMRendererOptions['patchProp'] = (
     (el as VueElement)._isVueCE &&
     (/[A-Z]/.test(key) || !isString(nextValue))
   ) {
-    patchDOMProp(el, camelize(key), nextValue, parentComponent)
+    patchDOMProp(el, camelize(key), nextValue, parentComponent, key)
   } else {
     // special case for <input v-model type="checkbox"> with
     // :true-value & :false-value