Ver Fonte

fix: install ssr helpers for functional context during SSR

close #7443, ref nuxt/nuxt.js#2565
Evan You há 8 anos atrás
pai
commit
9b22d86ab3

+ 2 - 0
flow/component.js

@@ -16,6 +16,8 @@ declare interface Component {
   static directive: (id: string, def?: Function | Object) => Function | Object | void;
   static component: (id: string, def?: Class<Component> | Object) => Class<Component>;
   static filter: (id: string, def?: Function) => Function | void;
+  // functional context constructor
+  static FunctionalRenderContext: Function;
 
   // public properties
   $el: any; // so that we can attach __vue__ to it

+ 1 - 1
scripts/config.js

@@ -123,7 +123,7 @@ const builds = {
     format: 'cjs',
     external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)
   },
-  'web-server-basic-renderer': {
+  'web-server-renderer-basic': {
     entry: resolve('web/entry-server-basic-renderer.js'),
     dest: resolve('packages/vue-server-renderer/basic.js'),
     format: 'umd',

+ 6 - 0
src/core/index.js

@@ -1,6 +1,7 @@
 import Vue from './instance/index'
 import { initGlobalAPI } from './global-api/index'
 import { isServerRendering } from 'core/util/env'
+import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
 
 initGlobalAPI(Vue)
 
@@ -15,6 +16,11 @@ Object.defineProperty(Vue.prototype, '$ssrContext', {
   }
 })
 
+// expose FunctionalRenderContext for ssr runtime helper installation
+Object.defineProperty(Vue, 'FunctionalRenderContext', {
+  value: FunctionalRenderContext
+})
+
 Vue.version = '__VERSION__'
 
 export default Vue

+ 6 - 6
src/core/vdom/create-functional-component.js

@@ -15,12 +15,12 @@ import {
   validateProp
 } from '../util/index'
 
-function FunctionalRenderContext (
-  data,
-  props,
-  children,
-  parent,
-  Ctor
+export function FunctionalRenderContext (
+  data: VNodeData,
+  props: Object,
+  children: ?Array<VNode>,
+  parent: Component,
+  Ctor: Class<Component>
 ) {
   const options = Ctor.options
   this.data = data

+ 21 - 14
src/server/optimizing-compiler/runtime-helpers.js

@@ -17,22 +17,29 @@ import {
   isRenderableAttr
 } from 'web/server/util'
 
+const ssrHelpers = {
+  _ssrEscape: escape,
+  _ssrNode: renderStringNode,
+  _ssrList: renderStringList,
+  _ssrAttr: renderAttr,
+  _ssrAttrs: renderAttrs,
+  _ssrDOMProps: renderDOMProps,
+  _ssrClass: renderSSRClass,
+  _ssrStyle: renderSSRStyle
+}
+
 export function installSSRHelpers (vm: Component) {
-  if (vm._ssrNode) return
-  let Ctor = vm.constructor
-  while (Ctor.super) {
-    Ctor = Ctor.super
+  if (vm._ssrNode) {
+    return
+  }
+  let Vue = vm.constructor
+  while (Vue.super) {
+    Vue = Vue.super
+  }
+  extend(Vue.prototype, ssrHelpers)
+  if (Vue.FunctionalRenderContext) {
+    extend(Vue.FunctionalRenderContext.prototype, ssrHelpers)
   }
-  extend(Ctor.prototype, {
-    _ssrEscape: escape,
-    _ssrNode: renderStringNode,
-    _ssrList: renderStringList,
-    _ssrAttr: renderAttr,
-    _ssrAttrs: renderAttrs,
-    _ssrDOMProps: renderDOMProps,
-    _ssrClass: renderSSRClass,
-    _ssrStyle: renderSSRStyle
-  })
 }
 
 class StringNode {

+ 19 - 0
test/ssr/ssr-string.spec.js

@@ -1145,6 +1145,25 @@ describe('SSR: renderToString', () => {
       done()
     })
   })
+
+  it('should expose ssr helpers on functional context', done => {
+    let called = false
+    renderVmWithOptions({
+      template: `<div><foo/></div>`,
+      components: {
+        foo: {
+          functional: true,
+          render (h, ctx) {
+            expect(ctx._ssrNode).toBeTruthy()
+            called = true
+          }
+        }
+      }
+    }, () => {
+      expect(called).toBe(true)
+      done()
+    })
+  })
 })
 
 function renderVmWithOptions (options, cb) {