| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- /* @flow */
- import VNode from './vnode'
- import { createElement } from './create-element'
- import { resolveInject } from '../instance/inject'
- import { resolveSlots } from '../instance/render-helpers/resolve-slots'
- import { installRenderHelpers } from '../instance/render-helpers/index'
- import {
- isDef,
- isTrue,
- camelize,
- emptyObject,
- validateProp
- } from '../util/index'
- function FunctionalRenderContext (
- data,
- props,
- children,
- parent,
- Ctor
- ) {
- const options = Ctor.options
- this.data = data
- this.props = props
- this.children = children
- this.parent = parent
- this.listeners = data.on || emptyObject
- this.injections = resolveInject(options.inject, parent)
- this.slots = () => resolveSlots(children, parent)
- // ensure the createElement function in functional components
- // gets a unique context - this is necessary for correct named slot check
- const contextVm = Object.create(parent)
- const isCompiled = isTrue(options._compiled)
- const needNormalization = !isCompiled
- // support for compiled functional template
- if (isCompiled) {
- // exposing $options for renderStatic()
- this.$options = options
- // pre-resolve slots for renderSlot()
- this.$slots = this.slots()
- this.$scopedSlots = data.scopedSlots || emptyObject
- }
- if (options._scopeId) {
- this._c = (a, b, c, d) => {
- const vnode: ?VNode = createElement(contextVm, a, b, c, d, needNormalization)
- if (vnode) {
- vnode.functionalScopeId = options._scopeId
- vnode.functionalContext = parent
- }
- return vnode
- }
- } else {
- this._c = (a, b, c, d) => createElement(contextVm, a, b, c, d, needNormalization)
- }
- }
- installRenderHelpers(FunctionalRenderContext.prototype)
- export function createFunctionalComponent (
- Ctor: Class<Component>,
- propsData: ?Object,
- data: VNodeData,
- contextVm: Component,
- children: ?Array<VNode>
- ): VNode | void {
- const options = Ctor.options
- const props = {}
- const propOptions = options.props
- if (isDef(propOptions)) {
- for (const key in propOptions) {
- props[key] = validateProp(key, propOptions, propsData || emptyObject)
- }
- } else {
- if (isDef(data.attrs)) mergeProps(props, data.attrs)
- if (isDef(data.props)) mergeProps(props, data.props)
- }
- const renderContext = new FunctionalRenderContext(
- data,
- props,
- children,
- contextVm,
- Ctor
- )
- const vnode = options.render.call(null, renderContext._c, renderContext)
- if (vnode instanceof VNode) {
- vnode.functionalContext = contextVm
- vnode.functionalOptions = options
- if (data.slot) {
- (vnode.data || (vnode.data = {})).slot = data.slot
- }
- }
- return vnode
- }
- function mergeProps (to, from) {
- for (const key in from) {
- to[camelize(key)] = from[key]
- }
- }
|