From 5b3f1e8424d40d2b7b1e07f53ec11570dd546d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B1=BC?= <31395977+leaon4@users.noreply.github.com> Date: Tue, 17 Aug 2021 03:46:27 +0800 Subject: [PATCH] fix(runtime-core): patchChildren first in patchElement (#4313) --- packages/runtime-core/src/renderer.ts | 58 +++++++++---------- .../runtime-dom/__tests__/patchProps.spec.ts | 22 +++++++ .../__tests__/testRuntime.spec.ts | 12 ++-- 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index fb7e6a46c85..17eaaf44d5c 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -840,6 +840,35 @@ function baseCreateRenderer( dynamicChildren = null } + const areChildrenSVG = isSVG && n2.type !== 'foreignObject' + if (dynamicChildren) { + patchBlockChildren( + n1.dynamicChildren!, + dynamicChildren, + el, + parentComponent, + parentSuspense, + areChildrenSVG, + slotScopeIds + ) + if (__DEV__ && parentComponent && parentComponent.type.__hmrId) { + traverseStaticChildren(n1, n2) + } + } else if (!optimized) { + // full diff + patchChildren( + n1, + n2, + el, + null, + parentComponent, + parentSuspense, + areChildrenSVG, + slotScopeIds, + false + ) + } + if (patchFlag > 0) { // the presence of a patchFlag means this element's render code was // generated by the compiler and can take the fast path. @@ -922,35 +951,6 @@ function baseCreateRenderer( ) } - const areChildrenSVG = isSVG && n2.type !== 'foreignObject' - if (dynamicChildren) { - patchBlockChildren( - n1.dynamicChildren!, - dynamicChildren, - el, - parentComponent, - parentSuspense, - areChildrenSVG, - slotScopeIds - ) - if (__DEV__ && parentComponent && parentComponent.type.__hmrId) { - traverseStaticChildren(n1, n2) - } - } else if (!optimized) { - // full diff - patchChildren( - n1, - n2, - el, - null, - parentComponent, - parentSuspense, - areChildrenSVG, - slotScopeIds, - false - ) - } - if ((vnodeHook = newProps.onVnodeUpdated) || dirs) { queuePostRenderEffect(() => { vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, n2, n1) diff --git a/packages/runtime-dom/__tests__/patchProps.spec.ts b/packages/runtime-dom/__tests__/patchProps.spec.ts index abcfb2c7123..3d00e51ccfe 100644 --- a/packages/runtime-dom/__tests__/patchProps.spec.ts +++ b/packages/runtime-dom/__tests__/patchProps.spec.ts @@ -192,4 +192,26 @@ describe('runtime-dom: props patching', () => { patchProp(el, 'size', 100, null) expect(el.getAttribute('size')).toBe(null) }) + + test('patch value for select', () => { + const root = document.createElement('div') + render( + h('select', { value: 'foo' }, [ + h('option', { value: 'foo' }, 'foo'), + h('option', { value: 'bar' }, 'bar') + ]), + root + ) + const el = root.children[0] as HTMLSelectElement + expect(el.value).toBe('foo') + + render( + h('select', { value: 'baz' }, [ + h('option', { value: 'foo' }, 'foo'), + h('option', { value: 'baz' }, 'baz') + ]), + root + ) + expect(el.value).toBe('baz') + }) }) diff --git a/packages/runtime-test/__tests__/testRuntime.spec.ts b/packages/runtime-test/__tests__/testRuntime.spec.ts index f3ca6eb2025..789ace25446 100644 --- a/packages/runtime-test/__tests__/testRuntime.spec.ts +++ b/packages/runtime-test/__tests__/testRuntime.spec.ts @@ -103,17 +103,17 @@ describe('test renderer', () => { expect(updateOps.length).toBe(2) expect(updateOps[0]).toEqual({ - type: NodeOpTypes.PATCH, + type: NodeOpTypes.SET_ELEMENT_TEXT, targetNode: root.children[0], - propKey: 'id', - propPrevValue: 'test', - propNextValue: 'foo' + text: 'bar' }) expect(updateOps[1]).toEqual({ - type: NodeOpTypes.SET_ELEMENT_TEXT, + type: NodeOpTypes.PATCH, targetNode: root.children[0], - text: 'bar' + propKey: 'id', + propPrevValue: 'test', + propNextValue: 'foo' }) })