Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b702b09

Browse filesBrowse files
committed
improvements for handling functional components with styles
1 parent 354f063 commit b702b09
Copy full SHA for b702b09

File tree

7 files changed

+113
-52
lines changed
Filter options

7 files changed

+113
-52
lines changed

‎lib/component-normalizer.js

Copy file name to clipboardExpand all lines: lib/component-normalizer.js
+20-15Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ module.exports = function normalizeComponent (
4040
if (moduleIdentifier) { // server build
4141
hook = function (context) {
4242
// 2.3 injection
43-
context = context || (this.$vnode && this.$vnode.ssrContext)
43+
context =
44+
context || // cached call
45+
(this.$vnode && this.$vnode.ssrContext) || // stateful
46+
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
4447
// 2.2 with runInNewContext: true
4548
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
4649
context = __VUE_SSR_CONTEXT__
@@ -61,23 +64,25 @@ module.exports = function normalizeComponent (
6164
hook = injectStyles
6265
}
6366

64-
var existing = options.functional ? options.render : options.beforeCreate
65-
66-
if (hook && options.functional && injectStyles) {
67-
// inject styles for functioal component in vue file
68-
options.render = function renderWithStyleInjection (h, context) {
69-
hook(context)
70-
return existing(h, context)
67+
if (hook) {
68+
var functional = options.functional
69+
var existing = functional
70+
? options.render
71+
: options.beforeCreate
72+
if (!functional) {
73+
// inject component registration as beforeCreate hook
74+
options.beforeCreate = existing
75+
? [].concat(existing, hook)
76+
: [hook]
77+
} else {
78+
// register for functioal component in vue file
79+
options.render = function renderWithStyleInjection (h, context) {
80+
hook.call(context)
81+
return existing(h, context)
82+
}
7183
}
7284
}
7385

74-
if (hook && !options.functional) {
75-
// inject component registration as beforeCreate hook
76-
options.beforeCreate = existing
77-
? [].concat(existing, hook)
78-
: [hook]
79-
}
80-
8186
return {
8287
esModule: esModule,
8388
exports: scriptExports,

‎package.json

Copy file name to clipboardExpand all lines: package.json
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@
7878
"stylus-loader": "^2.0.0",
7979
"sugarss": "^0.2.0",
8080
"url-loader": "^0.5.7",
81-
"vue": "^2.3.0-beta.1",
82-
"vue-server-renderer": "^2.3.0-beta.1",
83-
"vue-template-compiler": "^2.3.0-beta.1",
81+
"vue": "^2.3.2",
82+
"vue-server-renderer": "^2.3.2",
83+
"vue-template-compiler": "^2.3.2",
8484
"webpack": "^2.2.0"
8585
}
8686
}

‎test/fixtures/functional-style.vue

Copy file name to clipboard
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<script>
2+
export default {
3+
functional: true,
4+
render (h) {
5+
return h('div', { class: 'foo' }, ['functional'])
6+
}
7+
}
8+
</script>
9+
10+
<style>
11+
.foo { color: red; }
12+
</style>

‎test/fixtures/ssr-style.js

Copy file name to clipboard
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
var Vue = require('vue')
22
var App = require('./ssr-style.vue')
33

4-
module.exports = new Vue(App)
4+
module.exports = () => new Vue({
5+
render: h => h(App)
6+
})

‎test/fixtures/ssr-style.vue

Copy file name to clipboardExpand all lines: test/fixtures/ssr-style.vue
+6-1Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22
<div>
33
<h1>Hello</h1>
44
<basic/>
5+
<functional-style/>
56
</div>
67
</template>
78

89
<script>
910
import Basic from './basic.vue'
11+
import FunctionalStyle from './functional-style.vue'
1012
1113
export default {
12-
components: { Basic }
14+
components: {
15+
Basic,
16+
FunctionalStyle
17+
}
1318
}
1419
</script>
1520

‎test/test.js

Copy file name to clipboardExpand all lines: test/test.js
+38-15Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -84,29 +84,30 @@ function test (options, assert) {
8484
}
8585

8686
function mockRender (options, data) {
87+
function h (tag, data, children) {
88+
if (Array.isArray(data)) {
89+
children = data
90+
data = null
91+
}
92+
return {
93+
tag: tag,
94+
data: data,
95+
children: children
96+
}
97+
}
8798
return options.render.call(Object.assign({
8899
_v (val) {
89100
return val
90101
},
91102
_self: {},
92-
$createElement (tag, data, children) {
93-
if (Array.isArray(data)) {
94-
children = data
95-
data = null
96-
}
97-
return {
98-
tag: tag,
99-
data: data,
100-
children: children
101-
}
102-
},
103+
$createElement: h,
103104
_m (index) {
104105
return options.staticRenderFns[index].call(this)
105106
},
106107
_s (str) {
107108
return String(str)
108109
}
109-
}, data))
110+
}, data), h)
110111
}
111112

112113
function interopDefault (module) {
@@ -611,24 +612,28 @@ describe('vue-loader', function () {
611612
}
612613
}, code => {
613614
const renderer = SSR.createBundleRenderer(code, {
614-
basedir: __dirname
615+
basedir: __dirname,
616+
runInNewContext: 'once'
615617
})
616618
const context = {
617619
_registeredComponents: new Set()
618620
}
619621
renderer.renderToString(context, (err, res) => {
620622
if (err) return done(err)
621-
expect(res).to.contain('server-rendered')
623+
expect(res).to.contain('data-server-rendered')
622624
expect(res).to.contain('<h1>Hello</h1>')
623625
expect(res).to.contain('Hello from Component A!')
626+
expect(res).to.contain('<div class="foo">functional</div>')
624627
// from main component
625628
expect(context.styles).to.contain('h1 { color: green;')
626629
// from imported child component
627630
expect(context.styles).to.contain('comp-a h2 {\n color: #f00;')
628631
// from imported css file
629632
expect(context.styles).to.contain('h1 { color: red;')
633+
// from imported functional component
634+
expect(context.styles).to.contain('.foo { color: red;')
630635
// collect component identifiers during render
631-
expect(Array.from(context._registeredComponents).length).to.equal(2)
636+
expect(Array.from(context._registeredComponents).length).to.equal(3)
632637
done()
633638
})
634639
})
@@ -834,4 +839,22 @@ describe('vue-loader', function () {
834839
done()
835840
})
836841
})
842+
843+
it('functional component with styles', done => {
844+
test({
845+
entry: './test/fixtures/functional-style.vue'
846+
}, (window, module, rawModule) => {
847+
expect(module.functional).to.equal(true)
848+
var vnode = mockRender(module)
849+
// <div class="foo">hi</div>
850+
expect(vnode.tag).to.equal('div')
851+
expect(vnode.data.class).to.equal('foo')
852+
expect(vnode.children[0]).to.equal('functional')
853+
854+
var style = window.document.querySelector('style').textContent
855+
style = normalizeNewline(style)
856+
expect(style).to.contain('.foo { color: red;\n}')
857+
done()
858+
})
859+
})
837860
})

‎yarn.lock

Copy file name to clipboardExpand all lines: yarn.lock
+31-17Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,6 +2497,10 @@ lodash._isiterateecall@^3.0.0:
24972497
version "3.0.9"
24982498
resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
24992499

2500+
lodash._reinterpolate@~3.0.0:
2501+
version "3.0.0"
2502+
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
2503+
25002504
lodash.camelcase@^4.3.0:
25012505
version "4.3.0"
25022506
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
@@ -2533,6 +2537,19 @@ lodash.memoize@^4.1.2:
25332537
version "4.1.2"
25342538
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
25352539

2540+
lodash.template@^4.4.0:
2541+
version "4.4.0"
2542+
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0"
2543+
dependencies:
2544+
lodash._reinterpolate "~3.0.0"
2545+
lodash.templatesettings "^4.0.0"
2546+
2547+
lodash.templatesettings@^4.0.0:
2548+
version "4.1.0"
2549+
resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316"
2550+
dependencies:
2551+
lodash._reinterpolate "~3.0.0"
2552+
25362553
lodash.uniq@^4.5.0:
25372554
version "4.5.0"
25382555
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -4137,21 +4154,18 @@ vue-hot-reload-api@^2.1.0:
41374154
version "2.1.0"
41384155
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.1.0.tgz#9ca58a6e0df9078554ce1708688b6578754d86de"
41394156

4140-
vue-server-renderer@^2.3.0:
4141-
version "2.2.6"
4142-
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.2.6.tgz#0a20535544b6948bca076380d058e19bb1304eef"
4157+
vue-server-renderer@^2.3.2:
4158+
version "2.3.2"
4159+
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.3.2.tgz#01bfde9c524ef041873f1e2d18f9356c620b4f8c"
41434160
dependencies:
4144-
de-indent "^1.0.2"
4161+
chalk "^1.1.3"
4162+
hash-sum "^1.0.2"
41454163
he "^1.1.0"
4164+
lodash.template "^4.4.0"
4165+
lodash.uniq "^4.5.0"
41464166
resolve "^1.2.0"
4147-
source-map "0.5.6"
4148-
vue-ssr-html-stream "^2.1.0"
4149-
4150-
vue-ssr-html-stream@^2.1.0:
4151-
version "2.2.0"
4152-
resolved "https://registry.yarnpkg.com/vue-ssr-html-stream/-/vue-ssr-html-stream-2.2.0.tgz#56d78b96c9c172b43749a324c156e888aca96d92"
4153-
dependencies:
41544167
serialize-javascript "^1.3.0"
4168+
source-map "0.5.6"
41554169

41564170
vue-style-loader@^3.0.0:
41574171
version "3.0.1"
@@ -4160,9 +4174,9 @@ vue-style-loader@^3.0.0:
41604174
hash-sum "^1.0.2"
41614175
loader-utils "^1.0.2"
41624176

4163-
vue-template-compiler@^2.3.0:
4164-
version "2.2.6"
4165-
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.2.6.tgz#2e2928daf0cd0feca9dfc35a9729adeae173ec68"
4177+
vue-template-compiler@^2.3.2:
4178+
version "2.3.2"
4179+
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.3.2.tgz#d48a7f53df5f497033827182ceb4f0d340803017"
41664180
dependencies:
41674181
de-indent "^1.0.2"
41684182
he "^1.1.0"
@@ -4171,9 +4185,9 @@ vue-template-es2015-compiler@^1.2.2:
41714185
version "1.5.2"
41724186
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.5.2.tgz#a0a6c50c941d2a4abda963f2f42c337ac450ee95"
41734187

4174-
vue@^2.3.0:
4175-
version "2.2.6"
4176-
resolved "https://registry.yarnpkg.com/vue/-/vue-2.2.6.tgz#451714b394dd6d4eae7b773c40c2034a59621aed"
4188+
vue@^2.3.2:
4189+
version "2.3.2"
4190+
resolved "https://registry.yarnpkg.com/vue/-/vue-2.3.2.tgz#9e52aae3593480be235ff227557837e69f98203a"
41774191

41784192
watchpack@^1.3.1:
41794193
version "1.3.1"

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.