diff options
| author | ruki <waruqi@gmail.com> | 2018-11-08 00:38:48 +0800 |
|---|---|---|
| committer | ruki <waruqi@gmail.com> | 2018-11-07 21:53:09 +0800 |
| commit | 26105034da4fcce7ac883c899d781f016559310d (patch) | |
| tree | c459a5dc4e3aa0972d9919033ece511ce76dd129 /node_modules/vue/src/core/vdom/create-functional-component.js | |
| parent | 2c77f00f1a7ecb6c8192f9c16d3b2001b254a107 (diff) | |
| download | xmake-docs-26105034da4fcce7ac883c899d781f016559310d.tar.gz xmake-docs-26105034da4fcce7ac883c899d781f016559310d.zip | |
switch to vuepress
Diffstat (limited to 'node_modules/vue/src/core/vdom/create-functional-component.js')
| -rw-r--r-- | node_modules/vue/src/core/vdom/create-functional-component.js | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/node_modules/vue/src/core/vdom/create-functional-component.js b/node_modules/vue/src/core/vdom/create-functional-component.js new file mode 100644 index 00000000..efed801d --- /dev/null +++ b/node_modules/vue/src/core/vdom/create-functional-component.js @@ -0,0 +1,136 @@ +/* @flow */ + +import VNode, { cloneVNode } from './vnode' +import { createElement } from './create-element' +import { resolveInject } from '../instance/inject' +import { normalizeChildren } from '../vdom/helpers/normalize-children' +import { resolveSlots } from '../instance/render-helpers/resolve-slots' +import { installRenderHelpers } from '../instance/render-helpers/index' + +import { + isDef, + isTrue, + hasOwn, + camelize, + emptyObject, + validateProp +} from '../util/index' + +export function FunctionalRenderContext ( + data: VNodeData, + props: Object, + children: ?Array<VNode>, + parent: Component, + Ctor: Class<Component> +) { + const options = Ctor.options + // ensure the createElement function in functional components + // gets a unique context - this is necessary for correct named slot check + let contextVm + if (hasOwn(parent, '_uid')) { + contextVm = Object.create(parent) + // $flow-disable-line + contextVm._original = parent + } else { + // the context vm passed in is a functional context as well. + // in this case we want to make sure we are able to get a hold to the + // real context instance. + contextVm = parent + // $flow-disable-line + parent = parent._original + } + const isCompiled = isTrue(options._compiled) + const needNormalization = !isCompiled + + 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) + + // 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 = createElement(contextVm, a, b, c, d, needNormalization) + if (vnode && !Array.isArray(vnode)) { + vnode.fnScopeId = options._scopeId + vnode.fnContext = 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 | Array<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) { + return cloneAndMarkFunctionalResult(vnode, data, renderContext.parent, options) + } else if (Array.isArray(vnode)) { + const vnodes = normalizeChildren(vnode) || [] + const res = new Array(vnodes.length) + for (let i = 0; i < vnodes.length; i++) { + res[i] = cloneAndMarkFunctionalResult(vnodes[i], data, renderContext.parent, options) + } + return res + } +} + +function cloneAndMarkFunctionalResult (vnode, data, contextVm, options) { + // #7817 clone node before setting fnContext, otherwise if the node is reused + // (e.g. it was from a cached normal slot) the fnContext causes named slots + // that should not be matched to match. + const clone = cloneVNode(vnode) + clone.fnContext = contextVm + clone.fnOptions = options + if (data.slot) { + (clone.data || (clone.data = {})).slot = data.slot + } + return clone +} + +function mergeProps (to, from) { + for (const key in from) { + to[camelize(key)] = from[key] + } +} |
