]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(ssr): respect render function from extends/mixins in ssr (#3006)
authorHcySunYang <HcySunYang@outlook.com>
Thu, 25 Mar 2021 14:32:17 +0000 (22:32 +0800)
committerGitHub <noreply@github.com>
Thu, 25 Mar 2021 14:32:17 +0000 (10:32 -0400)
fix #3004

packages/runtime-core/src/component.ts
packages/server-renderer/__tests__/render.spec.ts
packages/server-renderer/src/render.ts

index bfb7736b4109cc1a641cbaec7ce40b330f14ae29..48f6f6e5ecb23deeb0153b0993b571333a497c50 100644 (file)
@@ -670,9 +670,13 @@ function finishComponentSetup(
 
   // template / render function normalization
   if (__NODE_JS__ && isSSR) {
-    if (Component.render) {
-      instance.render = Component.render as InternalRenderFunction
-    }
+    // 1. the render function may already exist, returned by `setup`
+    // 2. otherwise try to use the `Component.render`
+    // 3. if the component doesn't have a render function,
+    //    set `instance.render` to NOOP so that it can inherit the render function from mixins/extend
+    instance.render = (instance.render ||
+      Component.render ||
+      NOOP) as InternalRenderFunction
   } else if (!instance.render) {
     // could be set from setup()
     if (compile && Component.template && !Component.render) {
@@ -711,7 +715,8 @@ function finishComponentSetup(
   }
 
   // warn missing template/render
-  if (__DEV__ && !Component.render && instance.render === NOOP) {
+  // the runtime compilation of template in SSR is done by server-render
+  if (__DEV__ && !Component.render && instance.render === NOOP && !isSSR) {
     /* istanbul ignore if */
     if (!compile && Component.template) {
       warn(
index 29bccba85eadca32ef73eb59ba72184cb86e6f9a..e27fdf4bb562d700fc3cd7f97b2179002b58abe0 100644 (file)
@@ -99,6 +99,46 @@ function testRender(type: string, render: typeof renderToString) {
         ).toBe(`<div>hello</div>`)
       })
 
+      test('components using defineComponent with extends option', async () => {
+        expect(
+          await render(
+            createApp(
+              defineComponent({
+                extends: {
+                  data() {
+                    return { msg: 'hello' }
+                  },
+                  render(this: any) {
+                    return h('div', this.msg)
+                  }
+                }
+              })
+            )
+          )
+        ).toBe(`<div>hello</div>`)
+      })
+
+      test('components using defineComponent with mixins option', async () => {
+        expect(
+          await render(
+            createApp(
+              defineComponent({
+                mixins: [
+                  {
+                    data() {
+                      return { msg: 'hello' }
+                    },
+                    render(this: any) {
+                      return h('div', this.msg)
+                    }
+                  }
+                ]
+              })
+            )
+          )
+        ).toBe(`<div>hello</div>`)
+      })
+
       test('optimized components', async () => {
         expect(
           await render(
index fd40f3be4ce264e3495a46581c6a056c798868c6..c0ba83bea5b1e63574bb36bb7f24b3a42ae0fd75 100644 (file)
@@ -22,7 +22,8 @@ import {
   isString,
   isVoidTag,
   ShapeFlags,
-  isArray
+  isArray,
+  NOOP
 } from '@vue/shared'
 import { ssrRenderAttrs } from './helpers/ssrRenderAttrs'
 import { ssrCompile } from './helpers/ssrCompile'
@@ -118,7 +119,7 @@ function renderComponentSubTree(
     )
   } else {
     if (
-      !instance.render &&
+      (!instance.render || instance.render === NOOP) &&
       !instance.ssrRender &&
       !comp.ssrRender &&
       isString(comp.template)
@@ -155,7 +156,7 @@ function renderComponentSubTree(
         instance.ctx
       )
       setCurrentRenderingInstance(null)
-    } else if (instance.render) {
+    } else if (instance.render && instance.render !== NOOP) {
       renderVNode(
         push,
         (instance.subTree = renderComponentRoot(instance)),