Skip to content

Commit

Permalink
fix: fix scoped CSS for nested nodes in functional components
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Oct 11, 2017
1 parent 050bb33 commit 4216588
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 9 deletions.
3 changes: 2 additions & 1 deletion src/core/vdom/create-functional-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ function FunctionalRenderContext (
this._c = (a, b, c, d) => {
const vnode: ?VNode = createElement(contextVm, a, b, c, d, needNormalization)
if (vnode) {
vnode.fnScopeId = options._scopeId
vnode.functionalScopeId = options._scopeId
vnode.functionalContext = parent
}
return vnode
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/vdom/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ export function createPatchFunction (backend) {
// of going through the normal attribute patching process.
function setScope (vnode) {
let i
if (isDef(i = vnode.fnScopeId)) {
if (isDef(i = vnode.functionalScopeId)) {
nodeOps.setAttribute(vnode.elm, i, '')
} else {
let ancestor = vnode
Expand Down
9 changes: 7 additions & 2 deletions src/core/vdom/vnode.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ export default class VNode {
elm: Node | void;
ns: string | void;
context: Component | void; // rendered in this component's scope
functionalContext: Component | void; // only for functional component root nodes
key: string | number | void;
componentOptions: VNodeComponentOptions | void;
componentInstance: Component | void; // component instance
parent: VNode | void; // component placeholder node

// strictly internal
raw: boolean; // contains raw HTML? (server only)
isStatic: boolean; // hoisted static node
isRootInsert: boolean; // necessary for enter transition check
Expand All @@ -23,7 +24,9 @@ export default class VNode {
asyncMeta: Object | void;
isAsyncPlaceholder: boolean;
ssrContext: Object | void;
fnScopeId: ?string;
functionalContext: Component | void; // real context vm for functional nodes
functionalOptions: ?ComponentOptions; // for SSR caching
functionalScopeId: ?string; // functioanl scope id support

constructor (
tag?: string,
Expand All @@ -43,6 +46,8 @@ export default class VNode {
this.ns = undefined
this.context = context
this.functionalContext = undefined
this.functioanlOptions = undefined
this.functionalScopeId = undefined
this.key = data && data.key
this.componentOptions = componentOptions
this.componentInstance = undefined
Expand Down
14 changes: 9 additions & 5 deletions test/unit/features/options/_scopeId.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ describe('Options _scopeId', () => {
functional: true,
_scopeId: 'child',
render (h) {
return h('div', { class: 'child' }, 'child')
return h('div', { class: 'child' }, [
h('span', { class: 'child' }, 'child')
])
}
}
const vm = new Vue({
Expand All @@ -84,9 +86,11 @@ describe('Options _scopeId', () => {
}).$mount()

expect(vm.$el.hasAttribute('parent')).toBe(true)
const childEl = vm.$el.querySelector('.child')
expect(childEl.hasAttribute('child')).toBe(true)
// functional component with scopeId will not inherit parent scopeId
expect(childEl.hasAttribute('parent')).toBe(false)
const childEls = vm.$el.querySelectorAll('.child')
;[].forEach.call(childEls, el => {
expect(el.hasAttribute('child')).toBe(true)
// functional component with scopeId will not inherit parent scopeId
expect(el.hasAttribute('parent')).toBe(false)
})
})
})

0 comments on commit 4216588

Please sign in to comment.