Skip to content

Commit 4216588

Browse files
committed
fix: fix scoped CSS for nested nodes in functional components
1 parent 050bb33 commit 4216588

File tree

4 files changed

+19
-9
lines changed

4 files changed

+19
-9
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ function FunctionalRenderContext (
5151
this._c = (a, b, c, d) => {
5252
const vnode: ?VNode = createElement(contextVm, a, b, c, d, needNormalization)
5353
if (vnode) {
54-
vnode.fnScopeId = options._scopeId
54+
vnode.functionalScopeId = options._scopeId
55+
vnode.functionalContext = parent
5556
}
5657
return vnode
5758
}

src/core/vdom/patch.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ export function createPatchFunction (backend) {
281281
// of going through the normal attribute patching process.
282282
function setScope (vnode) {
283283
let i
284-
if (isDef(i = vnode.fnScopeId)) {
284+
if (isDef(i = vnode.functionalScopeId)) {
285285
nodeOps.setAttribute(vnode.elm, i, '')
286286
} else {
287287
let ancestor = vnode

src/core/vdom/vnode.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ export default class VNode {
88
elm: Node | void;
99
ns: string | void;
1010
context: Component | void; // rendered in this component's scope
11-
functionalContext: Component | void; // only for functional component root nodes
1211
key: string | number | void;
1312
componentOptions: VNodeComponentOptions | void;
1413
componentInstance: Component | void; // component instance
1514
parent: VNode | void; // component placeholder node
15+
16+
// strictly internal
1617
raw: boolean; // contains raw HTML? (server only)
1718
isStatic: boolean; // hoisted static node
1819
isRootInsert: boolean; // necessary for enter transition check
@@ -23,7 +24,9 @@ export default class VNode {
2324
asyncMeta: Object | void;
2425
isAsyncPlaceholder: boolean;
2526
ssrContext: Object | void;
26-
fnScopeId: ?string;
27+
functionalContext: Component | void; // real context vm for functional nodes
28+
functionalOptions: ?ComponentOptions; // for SSR caching
29+
functionalScopeId: ?string; // functioanl scope id support
2730

2831
constructor (
2932
tag?: string,
@@ -43,6 +46,8 @@ export default class VNode {
4346
this.ns = undefined
4447
this.context = context
4548
this.functionalContext = undefined
49+
this.functioanlOptions = undefined
50+
this.functionalScopeId = undefined
4651
this.key = data && data.key
4752
this.componentOptions = componentOptions
4853
this.componentInstance = undefined

test/unit/features/options/_scopeId.spec.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ describe('Options _scopeId', () => {
7474
functional: true,
7575
_scopeId: 'child',
7676
render (h) {
77-
return h('div', { class: 'child' }, 'child')
77+
return h('div', { class: 'child' }, [
78+
h('span', { class: 'child' }, 'child')
79+
])
7880
}
7981
}
8082
const vm = new Vue({
@@ -84,9 +86,11 @@ describe('Options _scopeId', () => {
8486
}).$mount()
8587

8688
expect(vm.$el.hasAttribute('parent')).toBe(true)
87-
const childEl = vm.$el.querySelector('.child')
88-
expect(childEl.hasAttribute('child')).toBe(true)
89-
// functional component with scopeId will not inherit parent scopeId
90-
expect(childEl.hasAttribute('parent')).toBe(false)
89+
const childEls = vm.$el.querySelectorAll('.child')
90+
;[].forEach.call(childEls, el => {
91+
expect(el.hasAttribute('child')).toBe(true)
92+
// functional component with scopeId will not inherit parent scopeId
93+
expect(el.hasAttribute('parent')).toBe(false)
94+
})
9195
})
9296
})

0 commit comments

Comments
 (0)