Evan You 10 лет назад
Родитель
Сommit
b1351be073
3 измененных файлов с 45 добавлено и 12 удалено
  1. 9 10
      src/platforms/web/server/modules/attrs.js
  2. 11 2
      src/server/render.js
  3. 25 0
      test/ssr/ssr-string.spec.js

+ 9 - 10
src/platforms/web/server/modules/attrs.js

@@ -6,20 +6,19 @@ import {
   isFalsyAttrValue
 } from 'web/util/attrs'
 
-export default function renderAttrs (node: VNodeWithData): ?string {
-  if (node.data.attrs || node.data.staticAttrs) {
-    return (
-      render(node.data.staticAttrs) +
-      render(node.data.attrs)
-    )
+export default function renderAttrs (node: VNodeWithData): string {
+  let res = ''
+  if (node.data.staticAttrs) {
+    res += render(node.data.staticAttrs)
+  }
+  if (node.data.attrs) {
+    res += render(node.data.attrs)
   }
+  return res
 }
 
-function render (attrs: ?{ [key: string]: any }): string {
+function render (attrs: { [key: string]: any }): string {
   let res = ''
-  if (!attrs) {
-    return res
-  }
   for (const key in attrs) {
     if (key === 'style') {
       // leave it to the style module

+ 11 - 2
src/server/render.js

@@ -18,8 +18,9 @@ export function createRenderFunction (
     isRoot: boolean
   ) {
     if (node.componentOptions) {
-      const child = createComponentInstanceForVnode(node)
-      renderNode(child._render(), write, next, isRoot)
+      const child = createComponentInstanceForVnode(node)._render()
+      child.parent = node
+      renderNode(child, write, next, isRoot)
     } else {
       if (node.tag) {
         renderElement(node, write, next, isRoot)
@@ -91,6 +92,14 @@ export function createRenderFunction (
         }
       }
     }
+    // attach scoped CSS ID
+    while (node) {
+      const scopeId = node.context.$options._scopeId
+      if (scopeId) {
+        markup += ` ${scopeId}`
+      }
+      node = node.parent
+    }
     return markup + '>'
   }
 

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

@@ -414,6 +414,31 @@ describe('SSR: renderToString', () => {
     })
   })
 
+  it('_scopeId', done => {
+    renderVmWithOptions({
+      _scopeId: '_v-parent',
+      template: '<div id="foo"><p><child></child></p></div>',
+      components: {
+        child: {
+          _scopeId: '_v-child',
+          render () {
+            const h = this.$createElement
+            return h('div', null, [h('span', null, ['foo'])])
+          }
+        }
+      }
+    }, result => {
+      expect(result).toContain(
+        '<div id="foo" server-rendered="true" _v-parent>' +
+          '<p _v-parent>' +
+            '<div _v-child _v-parent><span _v-child>foo</span></div>' +
+          '</p>' +
+        '</div>'
+      )
+      done()
+    })
+  })
+
   it('should catch error', done => {
     renderToString(new Vue({
       render () {