diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index db674f987d8..49ef212039b 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -2352,13 +2352,13 @@ function baseCreateRenderer( namespace, ) } + container._vnode = vnode if (!isFlushing) { isFlushing = true flushPreFlushCbs() flushPostFlushCbs() isFlushing = false } - container._vnode = vnode } const internals: RendererInternals = { diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 62ba166b030..449a85480c5 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -108,6 +108,7 @@ describe('defineCustomElement', () => { myInputEl.removeAttribute('value') await nextTick() expect(inputEl.value).toBe('') + app.unmount() }) test('should not unmount on move', async () => { @@ -772,4 +773,33 @@ describe('defineCustomElement', () => { ) }) }) + + // #9885 + test('avoid double mount when prop is set immediately after mount', () => { + customElements.define( + 'my-input-dupe', + defineCustomElement({ + props: { + value: String, + }, + render() { + return 'hello' + }, + }), + ) + createApp({ + render() { + return h('div', [ + h('my-input-dupe', { + onVnodeMounted(vnode) { + vnode.el!.value = 'fesfes' + }, + }), + ]) + }, + }).mount(container) + expect(container.children[0].children[0].shadowRoot?.innerHTML).toBe( + 'hello', + ) + }) })