mirror of https://github.com/vuejs/core.git
fix(custom-element): disconnect MutationObserver in nextTick in case that custom elements are moved (#10613)
Closes #10610
This commit is contained in:
parent
392bd9baa1
commit
bbb5be299b
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
type Ref,
|
||||
type VueElement,
|
||||
createApp,
|
||||
defineAsyncComponent,
|
||||
defineComponent,
|
||||
defineCustomElement,
|
||||
|
@ -60,6 +61,54 @@ describe('defineCustomElement', () => {
|
|||
expect(e.shadowRoot!.innerHTML).toBe('')
|
||||
})
|
||||
|
||||
// #10610
|
||||
test('When elements move, avoid prematurely disconnecting MutationObserver', async () => {
|
||||
const CustomInput = defineCustomElement({
|
||||
props: ['value'],
|
||||
emits: ['update'],
|
||||
setup(props, { emit }) {
|
||||
return () =>
|
||||
h('input', {
|
||||
type: 'number',
|
||||
value: props.value,
|
||||
onInput: (e: InputEvent) => {
|
||||
const num = (e.target! as HTMLInputElement).valueAsNumber
|
||||
emit('update', Number.isNaN(num) ? null : num)
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
customElements.define('my-el-input', CustomInput)
|
||||
const num = ref('12')
|
||||
const containerComp = defineComponent({
|
||||
setup() {
|
||||
return () => {
|
||||
return h('div', [
|
||||
h('my-el-input', {
|
||||
value: num.value,
|
||||
onUpdate: ($event: CustomEvent) => {
|
||||
num.value = $event.detail[0]
|
||||
},
|
||||
}),
|
||||
h('div', { id: 'move' }),
|
||||
])
|
||||
}
|
||||
},
|
||||
})
|
||||
const app = createApp(containerComp)
|
||||
app.mount(container)
|
||||
const myInputEl = container.querySelector('my-el-input')!
|
||||
const inputEl = myInputEl.shadowRoot!.querySelector('input')!
|
||||
await nextTick()
|
||||
expect(inputEl.value).toBe('12')
|
||||
const moveEl = container.querySelector('#move')!
|
||||
moveEl.append(myInputEl)
|
||||
await nextTick()
|
||||
myInputEl.removeAttribute('value')
|
||||
await nextTick()
|
||||
expect(inputEl.value).toBe('')
|
||||
})
|
||||
|
||||
test('should not unmount on move', async () => {
|
||||
container.innerHTML = `<div><my-element></my-element></div>`
|
||||
const e = container.childNodes[0].childNodes[0] as VueElement
|
||||
|
|
|
@ -215,12 +215,12 @@ export class VueElement extends BaseClass {
|
|||
|
||||
disconnectedCallback() {
|
||||
this._connected = false
|
||||
nextTick(() => {
|
||||
if (!this._connected) {
|
||||
if (this._ob) {
|
||||
this._ob.disconnect()
|
||||
this._ob = null
|
||||
}
|
||||
nextTick(() => {
|
||||
if (!this._connected) {
|
||||
render(null, this.shadowRoot!)
|
||||
this._instance = null
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue