From e16e9a7341e7cfb3c443da4e5e5b06e8158712c3 Mon Sep 17 00:00:00 2001 From: edison Date: Fri, 11 Oct 2024 09:52:06 +0800 Subject: [PATCH] fix(custom-element): properly remove hyphenated attribute (#12143) close #12139 --- .../__tests__/customElement.spec.ts | 35 +++++++++++++++++++ packages/runtime-dom/src/modules/props.ts | 3 +- packages/runtime-dom/src/patchProp.ts | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index ef5051f42f7..6b9f7d1391e 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/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( + ``, + ) + + toggle.value = false + await nextTick() + expect(el.hasAttribute('foo-bar')).toBe(false) + expect((el as any).outerHTML).toBe( + ``, + ) + }) }) diff --git a/packages/runtime-dom/src/modules/props.ts b/packages/runtime-dom/src/modules/props.ts index 93d45c9e160..98608831a9a 100644 --- a/packages/runtime-dom/src/modules/props.ts +++ b/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) } diff --git a/packages/runtime-dom/src/patchProp.ts b/packages/runtime-dom/src/patchProp.ts index 5814e77c4f8..b6af8997112 100644 --- a/packages/runtime-dom/src/patchProp.ts +++ b/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 with // :true-value & :false-value