mirror of https://github.com/vuejs/core.git
fix(custom-element): set prop runs pending mutations before disconnect (#13897)
close #13315
This commit is contained in:
parent
e388f1a09f
commit
c4a88cdd0d
|
@ -223,6 +223,31 @@ describe('defineCustomElement', () => {
|
||||||
expect(e.getAttribute('baz-qux')).toBe('four')
|
expect(e.getAttribute('baz-qux')).toBe('four')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('props via attributes and properties changed together', async () => {
|
||||||
|
const e = new E()
|
||||||
|
e.foo = 'foo1'
|
||||||
|
e.bar = { x: 'bar1' }
|
||||||
|
container.appendChild(e)
|
||||||
|
await nextTick()
|
||||||
|
expect(e.shadowRoot!.innerHTML).toBe('<div>foo1</div><div>bar1</div>')
|
||||||
|
|
||||||
|
// change attr then property
|
||||||
|
e.setAttribute('foo', 'foo2')
|
||||||
|
e.bar = { x: 'bar2' }
|
||||||
|
await nextTick()
|
||||||
|
expect(e.shadowRoot!.innerHTML).toBe('<div>foo2</div><div>bar2</div>')
|
||||||
|
expect(e.getAttribute('foo')).toBe('foo2')
|
||||||
|
expect(e.hasAttribute('bar')).toBe(false)
|
||||||
|
|
||||||
|
// change prop then attr
|
||||||
|
e.bar = { x: 'bar3' }
|
||||||
|
e.setAttribute('foo', 'foo3')
|
||||||
|
await nextTick()
|
||||||
|
expect(e.shadowRoot!.innerHTML).toBe('<div>foo3</div><div>bar3</div>')
|
||||||
|
expect(e.getAttribute('foo')).toBe('foo3')
|
||||||
|
expect(e.hasAttribute('bar')).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
test('props via hyphen property', async () => {
|
test('props via hyphen property', async () => {
|
||||||
const Comp = defineCustomElement({
|
const Comp = defineCustomElement({
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -346,6 +346,12 @@ export class VueElement
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _processMutations(mutations: MutationRecord[]) {
|
||||||
|
for (const m of mutations) {
|
||||||
|
this._setAttr(m.attributeName!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* resolve inner component definition (handle possible async component)
|
* resolve inner component definition (handle possible async component)
|
||||||
*/
|
*/
|
||||||
|
@ -360,11 +366,7 @@ export class VueElement
|
||||||
}
|
}
|
||||||
|
|
||||||
// watch future attr changes
|
// watch future attr changes
|
||||||
this._ob = new MutationObserver(mutations => {
|
this._ob = new MutationObserver(this._processMutations.bind(this))
|
||||||
for (const m of mutations) {
|
|
||||||
this._setAttr(m.attributeName!)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this._ob.observe(this, { attributes: true })
|
this._ob.observe(this, { attributes: true })
|
||||||
|
|
||||||
|
@ -514,7 +516,10 @@ export class VueElement
|
||||||
// reflect
|
// reflect
|
||||||
if (shouldReflect) {
|
if (shouldReflect) {
|
||||||
const ob = this._ob
|
const ob = this._ob
|
||||||
ob && ob.disconnect()
|
if (ob) {
|
||||||
|
this._processMutations(ob.takeRecords())
|
||||||
|
ob.disconnect()
|
||||||
|
}
|
||||||
if (val === true) {
|
if (val === true) {
|
||||||
this.setAttribute(hyphenate(key), '')
|
this.setAttribute(hyphenate(key), '')
|
||||||
} else if (typeof val === 'string' || typeof val === 'number') {
|
} else if (typeof val === 'string' || typeof val === 'number') {
|
||||||
|
|
Loading…
Reference in New Issue