diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts
index bb08fb155..fb746f72c 100644
--- a/packages/runtime-dom/__tests__/customElement.spec.ts
+++ b/packages/runtime-dom/__tests__/customElement.spec.ts
@@ -139,6 +139,12 @@ describe('defineCustomElement', () => {
expect(e.shadowRoot!.innerHTML).toBe('
two
')
expect(e.hasAttribute('foo')).toBe(false)
+ e.foo = undefined
+ await nextTick()
+ expect(e.shadowRoot!.innerHTML).toBe('two
')
+ expect(e.hasAttribute('foo')).toBe(false)
+ expect(e.foo).toBe(undefined)
+
e.bazQux = 'four'
await nextTick()
expect(e.shadowRoot!.innerHTML).toBe('four
')
diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts
index 337a3d90f..01ce2bad4 100644
--- a/packages/runtime-dom/src/apiCustomElement.ts
+++ b/packages/runtime-dom/src/apiCustomElement.ts
@@ -313,7 +313,7 @@ export class VueElement extends BaseClass {
}
protected _setAttr(key: string) {
- let value = this.getAttribute(key)
+ let value = this.hasAttribute(key) ? this.getAttribute(key) : undefined
const camelKey = camelize(key)
if (this._numberProps && this._numberProps[camelKey]) {
value = toNumber(value)