Skip to content

Commit

Permalink
fix(src/server/render.js): Fixes component directives rendering
Browse files Browse the repository at this point in the history
Component directives are not being render during SSR, this fixes it by passing the directives data
to its first imediate child.

fix vuejs#10733
  • Loading branch information
trecenti committed Apr 6, 2020
1 parent 5396342 commit 8b984f4
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 2 deletions.
7 changes: 6 additions & 1 deletion src/server/render.js
Expand Up @@ -201,6 +201,11 @@ function renderComponentInner (node, isRoot, context) {
type: 'Component',
prevActive
})
if (isDef(node.data) && isDef(node.data.directives)) {
childNode.data = (childNode.data || {})
childNode.data.directives = node.data.directives
childNode.isComponentRootElement = true
}
renderNode(childNode, isRoot, context)
}

Expand Down Expand Up @@ -364,7 +369,7 @@ function renderStartingTag (node: VNode, context) {
if (dirRenderer) {
// directives mutate the node's data
// which then gets rendered by modules
dirRenderer(node, dirs[i])
dirRenderer(node.isComponentRootElement ? node.parent : node, dirs[i])
}
}
}
Expand Down
76 changes: 75 additions & 1 deletion test/ssr/ssr-string.spec.js
Expand Up @@ -829,7 +829,7 @@ describe('SSR: renderToString', () => {
})
})

it('custom directives', done => {
it('custom directives on raw element', done => {
const renderer = createRenderer({
directives: {
'class-prefixer': (node, dir) => {
Expand Down Expand Up @@ -861,6 +861,80 @@ describe('SSR: renderToString', () => {
})
})

it('custom directives on component', done => {
const Test = {
template: '<span>hello world</span>'
}
const renderer = createRenderer({
directives: {
'class-prefixer': (node, dir) => {
if (node.data.class) {
node.data.class = `${dir.value}-${node.data.class}`
}
if (node.data.staticClass) {
node.data.staticClass = `${dir.value}-${node.data.staticClass}`
}
}
}
})
renderer.renderToString(new Vue({
template: '<p><Test v-class-prefixer="\'my\'" class="class1" :class="\'class2\'" /></p>',
components: { Test },
}), (err, result) => {
expect(err).toBeNull()
expect(result).toContain('<p data-server-rendered="true"><span class="my-class1 my-class2">hello world</span></p>')
done()
})
})

it('custom directives on element root of a component', done => {
const Test = {
template: '<span v-class-prefixer="\'my\'" class="class1" :class="\'class2\'">hello world</span>'
}
const renderer = createRenderer({
directives: {
'class-prefixer': (node, dir) => {
if (node.data.class) {
node.data.class = `${dir.value}-${node.data.class}`
}
if (node.data.staticClass) {
node.data.staticClass = `${dir.value}-${node.data.staticClass}`
}
}
}
})
renderer.renderToString(new Vue({
template: '<p><Test /></p>',
components: { Test },
}), (err, result) => {
expect(err).toBeNull()
expect(result).toContain('<p data-server-rendered="true"><span class="my-class1 my-class2">hello world</span></p>')
done()
})
})

it('custom directives on element with parent element', done => {
const renderer = createRenderer({
directives: {
'class-prefixer': (node, dir) => {
if (node.data.class) {
node.data.class = `${dir.value}-${node.data.class}`
}
if (node.data.staticClass) {
node.data.staticClass = `${dir.value}-${node.data.staticClass}`
}
}
}
})
renderer.renderToString(new Vue({
template: '<p><span v-class-prefixer="\'my\'" class="class1" :class="\'class2\'">hello world</span></p>',
}), (err, result) => {
expect(err).toBeNull()
expect(result).toContain('<p data-server-rendered="true"><span class="my-class1 my-class2">hello world</span></p>')
done()
})
})

it('should not warn for custom directives that do not have server-side implementation', done => {
renderToString(new Vue({
directives: {
Expand Down

0 comments on commit 8b984f4

Please sign in to comment.