Преглед изворни кода

fix(KeepAlive): adapt keepalive for ssr (#3259)

fix #3255
HcySunYang пре 5 година
родитељ
комит
e8e9b00f81

+ 13 - 6
packages/runtime-core/src/components/KeepAlive.ts

@@ -77,19 +77,26 @@ const KeepAliveImpl = {
   },
 
   setup(props: KeepAliveProps, { slots }: SetupContext) {
-    const cache: Cache = new Map()
-    const keys: Keys = new Set()
-    let current: VNode | null = null
-
     const instance = getCurrentInstance()!
-    const parentSuspense = instance.suspense
-
     // KeepAlive communicates with the instantiated renderer via the
     // ctx where the renderer passes in its internals,
     // and the KeepAlive instance exposes activate/deactivate implementations.
     // The whole point of this is to avoid importing KeepAlive directly in the
     // renderer to facilitate tree-shaking.
     const sharedContext = instance.ctx as KeepAliveContext
+
+    // if the internal renderer is not registered, it indicates that this is server-side rendering,
+    // for KeepAlive, we just need to render its children
+    if (!sharedContext.renderer) {
+      return slots.default
+    }
+
+    const cache: Cache = new Map()
+    const keys: Keys = new Set()
+    let current: VNode | null = null
+
+    const parentSuspense = instance.suspense
+
     const {
       renderer: {
         p: patch,

+ 12 - 0
packages/server-renderer/__tests__/render.spec.ts

@@ -8,6 +8,7 @@ import {
   defineComponent,
   createTextVNode,
   createStaticVNode,
+  KeepAlive,
   withCtx
 } from 'vue'
 import { escapeHtml } from '@vue/shared'
@@ -604,6 +605,17 @@ function testRender(type: string, render: typeof renderToString) {
       })
     })
 
+    describe('vnode component', () => {
+      test('KeepAlive', async () => {
+        const MyComp = {
+          render: () => h('p', 'hello')
+        }
+        expect(await render(h(KeepAlive, () => h(MyComp)))).toBe(
+          `<!--[--><p>hello</p><!--]-->`
+        )
+      })
+    })
+
     describe('raw vnode types', () => {
       test('Text', async () => {
         expect(await render(createTextVNode('hello <div>'))).toBe(