Bladeren bron

fix(runtime-core): patchChildren first in patchElement (#4313)

4 jaren geleden
bovenliggende
commit
5b3f1e8424

+ 29 - 29
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)

+ 22 - 0
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')
+  })
 })

+ 6 - 6
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'
     })
   })