fix(custom-element): delete prop on attribute removal

close #11276
This commit is contained in:
Evan You 2024-08-08 18:37:54 +08:00
parent be84f33ab0
commit 506c4c53fd
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
2 changed files with 32 additions and 3 deletions

View File

@ -1241,4 +1241,25 @@ describe('defineCustomElement', () => {
expect(e.shadowRoot!.innerHTML).toBe(`<div>fooValue</div>`)
app.unmount()
})
// #11276
test('delete prop on attr removal', async () => {
const E = defineCustomElement({
props: {
boo: {
type: Boolean,
},
},
render() {
return this.boo + ',' + typeof this.boo
},
})
customElements.define('el-attr-removal', E)
container.innerHTML = '<el-attr-removal boo>'
const e = container.childNodes[0] as VueElement
expect(e.shadowRoot!.innerHTML).toBe(`true,boolean`)
e.removeAttribute('boo')
await nextTick()
expect(e.shadowRoot!.innerHTML).toBe(`false,boolean`)
})
})

View File

@ -42,6 +42,9 @@ import {
} from '@vue/shared'
import { createApp, createSSRApp, render } from '.'
// marker for attr removal
const REMOVAL = {}
export type VueElementConstructor<P = {}> = {
new (initialProps?: Record<string, any>): VueElement & P
}
@ -455,9 +458,10 @@ export class VueElement
protected _setAttr(key: string) {
if (key.startsWith('data-v-')) return
let value = this.hasAttribute(key) ? this.getAttribute(key) : undefined
const has = this.hasAttribute(key)
let value = has ? this.getAttribute(key) : REMOVAL
const camelKey = camelize(key)
if (this._numberProps && this._numberProps[camelKey]) {
if (has && this._numberProps && this._numberProps[camelKey]) {
value = toNumber(value)
}
this._setProp(camelKey, value, false, true)
@ -475,7 +479,11 @@ export class VueElement
*/
_setProp(key: string, val: any, shouldReflect = true, shouldUpdate = false) {
if (val !== this._props[key]) {
this._props[key] = val
if (val === REMOVAL) {
delete this._props[key]
} else {
this._props[key] = val
}
if (shouldUpdate && this._instance) {
this._update()
}