소스 검색

fix(hydration): handling empty text nodes

daiwei 10 달 전
부모
커밋
167df1e381
3개의 변경된 파일29개의 추가작업 그리고 7개의 파일을 삭제
  1. 1 1
      packages/compiler-vapor/src/generators/text.ts
  2. 14 0
      packages/runtime-vapor/__tests__/hydration.spec.ts
  3. 14 6
      packages/runtime-vapor/src/dom/node.ts

+ 1 - 1
packages/compiler-vapor/src/generators/text.ts

@@ -70,6 +70,6 @@ export function genGetTextChild(
 
   return [
     NEWLINE,
-    `const x${oper.parent} = ${context.helper('child')}(n${oper.parent})`,
+    `const x${oper.parent} = ${context.helper('child')}(n${oper.parent}, -1)`,
   ]
 }

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

@@ -182,6 +182,20 @@ describe('Vapor Mode hydration', () => {
         `"<!--[--><span></span>barAbarBbar<span></span><!--]-->"`,
       )
     })
+
+    test('empty text nodes', async () => {
+      const data = reactive({ txt: '' })
+      const { container } = await testHydration(
+        `<template><div>{{ data.txt }}</div></template>`,
+        undefined,
+        data,
+      )
+      expect(container.innerHTML).toMatchInlineSnapshot(`"<div> </div>"`)
+
+      data.txt = 'foo'
+      await nextTick()
+      expect(container.innerHTML).toMatchInlineSnapshot(`"<div>foo</div>"`)
+    })
   })
 
   describe('element', () => {

+ 14 - 6
packages/runtime-vapor/src/dom/node.ts

@@ -60,15 +60,23 @@ export function _child(node: ParentNode): Node {
  */
 /*! #__NO_SIDE_EFFECTS__ */
 export function __child(node: ParentNode, offset?: number): Node {
-  let n = offset ? __nthChild(node, offset) : node.firstChild!
-
-  if (isComment(n, '[')) {
-    n = locateEndAnchor(n)!.nextSibling!
+  // when offset is -1, it means we need to get the text node of this element
+  // since server-side rendering doesn't generate whitespace placeholder text nodes,
+  // if firstChild is null, manually insert a text node and return it
+  if (offset === -1 && !node.firstChild) {
+    node.textContent = ' '
+    return node.firstChild!
   }
 
-  while (n && isVaporAnchors(n)) {
-    n = n.nextSibling!
+  let n = offset ? __nthChild(node, offset) : node.firstChild!
+  while (n && (isComment(n, '[') || isVaporAnchors(n))) {
+    if (isComment(n, '[')) {
+      n = locateEndAnchor(n)!.nextSibling!
+    } else {
+      n = n.nextSibling!
+    }
   }
+
   return n
 }