Skip to content

Commit 506c4c5

Browse files
committed
fix(custom-element): delete prop on attribute removal
close #11276
1 parent be84f33 commit 506c4c5

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

Diff for: packages/runtime-dom/__tests__/customElement.spec.ts

+21
Original file line numberDiff line numberDiff line change
@@ -1241,4 +1241,25 @@ describe('defineCustomElement', () => {
12411241
expect(e.shadowRoot!.innerHTML).toBe(`<div>fooValue</div>`)
12421242
app.unmount()
12431243
})
1244+
1245+
// #11276
1246+
test('delete prop on attr removal', async () => {
1247+
const E = defineCustomElement({
1248+
props: {
1249+
boo: {
1250+
type: Boolean,
1251+
},
1252+
},
1253+
render() {
1254+
return this.boo + ',' + typeof this.boo
1255+
},
1256+
})
1257+
customElements.define('el-attr-removal', E)
1258+
container.innerHTML = '<el-attr-removal boo>'
1259+
const e = container.childNodes[0] as VueElement
1260+
expect(e.shadowRoot!.innerHTML).toBe(`true,boolean`)
1261+
e.removeAttribute('boo')
1262+
await nextTick()
1263+
expect(e.shadowRoot!.innerHTML).toBe(`false,boolean`)
1264+
})
12441265
})

Diff for: packages/runtime-dom/src/apiCustomElement.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ import {
4242
} from '@vue/shared'
4343
import { createApp, createSSRApp, render } from '.'
4444

45+
// marker for attr removal
46+
const REMOVAL = {}
47+
4548
export type VueElementConstructor<P = {}> = {
4649
new (initialProps?: Record<string, any>): VueElement & P
4750
}
@@ -455,9 +458,10 @@ export class VueElement
455458

456459
protected _setAttr(key: string) {
457460
if (key.startsWith('data-v-')) return
458-
let value = this.hasAttribute(key) ? this.getAttribute(key) : undefined
461+
const has = this.hasAttribute(key)
462+
let value = has ? this.getAttribute(key) : REMOVAL
459463
const camelKey = camelize(key)
460-
if (this._numberProps && this._numberProps[camelKey]) {
464+
if (has && this._numberProps && this._numberProps[camelKey]) {
461465
value = toNumber(value)
462466
}
463467
this._setProp(camelKey, value, false, true)
@@ -475,7 +479,11 @@ export class VueElement
475479
*/
476480
_setProp(key: string, val: any, shouldReflect = true, shouldUpdate = false) {
477481
if (val !== this._props[key]) {
478-
this._props[key] = val
482+
if (val === REMOVAL) {
483+
delete this._props[key]
484+
} else {
485+
this._props[key] = val
486+
}
479487
if (shouldUpdate && this._instance) {
480488
this._update()
481489
}

0 commit comments

Comments
 (0)