Jelajahi Sumber

fix(custom-element): properly remove hyphenated attribute (#12143)

close #12139
edison 1 tahun lalu
induk
melakukan
e16e9a7341

+ 35 - 0
packages/runtime-dom/__tests__/customElement.spec.ts

@@ -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>`,
+    )
+  })
 })

+ 2 - 1
packages/runtime-dom/src/modules/props.ts

@@ -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)
 }

+ 1 - 1
packages/runtime-dom/src/patchProp.ts

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