Просмотр исходного кода

fix: handling v-for with non-hydration nodes

daiwei 6 месяцев назад
Родитель
Сommit
7044f6ff52

+ 51 - 0
packages/runtime-vapor/__tests__/hydration.spec.ts

@@ -1940,6 +1940,57 @@ describe('Vapor Mode hydration', () => {
         </div>"
       `)
     })
+
+    test('with non-hydration node', async () => {
+      const data = ref({ show: true, msg: 'foo' })
+      const { container } = await testHydration(
+        `<template>
+          <div>
+            <div v-for="item in 2">
+              <div>
+                <div v-if="data.show">{{ data.msg }}</div>
+              </div>
+              <span>non-hydration node</span>
+            </div>
+          </div>
+        </template>`,
+        {},
+        data,
+      )
+      expect(formatHtml(container.innerHTML)).toMatchInlineSnapshot(
+        `
+        "<div>
+        <!--[--><div><div><div>foo</div><!--if--></div><span>non-hydration node</span></div><div><div><div>foo</div><!--if--></div><span>non-hydration node</span></div><!--]-->
+        </div>"
+      `,
+      )
+
+      data.value.msg = 'bar'
+      await nextTick()
+      expect(formatHtml(container.innerHTML)).toMatchInlineSnapshot(
+        `
+        "<div>
+        <!--[--><div><div><div>bar</div><!--if--></div><span>non-hydration node</span></div><div><div><div>bar</div><!--if--></div><span>non-hydration node</span></div><!--]-->
+        </div>"
+      `,
+      )
+
+      data.value.show = false
+      await nextTick()
+      expect(formatHtml(container.innerHTML)).toMatchInlineSnapshot(`
+        "<div>
+        <!--[--><div><div><!--if--></div><span>non-hydration node</span></div><div><div><!--if--></div><span>non-hydration node</span></div><!--]-->
+        </div>"
+      `)
+
+      data.value.show = true
+      await nextTick()
+      expect(formatHtml(container.innerHTML)).toMatchInlineSnapshot(`
+        "<div>
+        <!--[--><div><div><div>bar</div><!--if--></div><span>non-hydration node</span></div><div><div><div>bar</div><!--if--></div><span>non-hydration node</span></div><!--]-->
+        </div>"
+      `)
+    })
   })
 
   describe('slots', () => {

+ 3 - 7
packages/runtime-vapor/src/apiCreateFor.ts

@@ -132,18 +132,14 @@ export const createFor = (
 
     if (!isMounted) {
       isMounted = true
-      let prevNodes: Block
       for (let i = 0; i < newLength; i++) {
-        if (isHydrating && isComponent && i > 0) {
-          setCurrentHydrationNode(findLastChild(prevNodes!)!.nextSibling)
+        const nodes = mount(source, i).nodes
+        if (isHydrating) {
+          setCurrentHydrationNode(findLastChild(nodes!)!.nextSibling)
         }
-        prevNodes = mount(source, i).nodes
       }
 
       if (isHydrating) {
-        if (isComponent) {
-          setCurrentHydrationNode(findLastChild(prevNodes!)!.nextSibling)
-        }
         parentAnchor =
           newLength === 0
             ? currentHydrationNode!.nextSibling!