Explorar o código

support slots in functional components

Evan You %!s(int64=9) %!d(string=hai) anos
pai
achega
23a22cbb44

+ 9 - 8
src/core/instance/render.js

@@ -56,9 +56,7 @@ export function renderMixin (Vue: Class<Component>) {
     vm.$vnode = _parentVnode
     // resolve slots. becaues slots are rendered in parent scope,
     // we set the activeInstance to parent.
-    if (_renderChildren) {
-      resolveSlots(vm, _renderChildren)
-    }
+    vm.$slots = resolveSlots(_renderChildren)
     // render self
     let vnode
     try {
@@ -179,11 +177,13 @@ export function renderMixin (Vue: Class<Component>) {
   }
 }
 
-function resolveSlots (
-  vm: Component,
-  renderChildren: Array<any> | () => Array<any> | string
-) {
-  const slots = vm.$slots = {}
+export function resolveSlots (
+  renderChildren?: Array<any> | () => Array<any> | string
+): Object {
+  const slots = {}
+  if (!renderChildren) {
+    return slots
+  }
   const children = normalizeChildren(renderChildren) || []
   const defaultSlot = []
   let name, child
@@ -208,4 +208,5 @@ function resolveSlots (
   )) {
     slots.default = defaultSlot
   }
+  return slots
 }

+ 8 - 1
src/core/vdom/create-component.js

@@ -4,6 +4,7 @@ import Vue from '../instance/index'
 import VNode from './vnode'
 import { normalizeChildren } from './helpers'
 import { callHook } from '../instance/lifecycle'
+import { resolveSlots } from '../instance/render'
 import { warn, isObject, hasOwn, hyphenate, validateProp } from '../util/index'
 
 const hooks = { init, prepatch, insert, destroy }
@@ -79,7 +80,13 @@ export function createComponent (
     return Ctor.options.render.call(
       null,
       parent.$createElement,
-      { props, parent, data, children: () => normalizeChildren(children) }
+      {
+        props,
+        parent,
+        data,
+        children: () => normalizeChildren(children),
+        slots: () => resolveSlots(children)
+      }
     )
   }
 

+ 18 - 0
test/unit/features/options/functional.spec.js

@@ -22,6 +22,24 @@ describe('Options functional', () => {
     }).then(done)
   })
 
+  it('should support slots', () => {
+    const vm = new Vue({
+      data: { test: 'foo' },
+      template: '<div><wrap><div slot="a">foo</div><div slot="b">bar</div></wrap></div>',
+      components: {
+        wrap: {
+          functional: true,
+          props: ['msg'],
+          render (h, { slots }) {
+            slots = slots()
+            return h('div', null, [slots.b, slots.a])
+          }
+        }
+      }
+    }).$mount()
+    expect(vm.$el.innerHTML).toBe('<div><div>bar</div><div>foo</div></div>')
+  })
+
   it('should let vnode raw data pass through', done => {
     const onValid = jasmine.createSpy('valid')
     const vm = new Vue({