Просмотр исходного кода

fix: fix scoped CSS for nested nodes in functional components

Evan You 8 лет назад
Родитель
Сommit
421658884f

+ 2 - 1
src/core/vdom/create-functional-component.js

@@ -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
     }

+ 1 - 1
src/core/vdom/patch.js

@@ -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

+ 7 - 2
src/core/vdom/vnode.js

@@ -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
@@ -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,
@@ -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

+ 9 - 5
test/unit/features/options/_scopeId.spec.js

@@ -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({
@@ -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)
+    })
   })
 })