-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
createComponent
上一部分学习到了 createComponent 方法是在哪个地方因为什么条件进行了调用,这里来继续深入,看一看 createComponent 的具体实现是怎样的,其定义在 /src/core/vdom/create-component.js中:
export function createComponent (
Ctor: Class<Component> | Function | Object | void,
data: ?VNodeData,
context: Component,
children: ?Array<VNode>,
tag?: string
): VNode | Array<VNode> | void {
if (isUndef(Ctor)) {
return
}
// 这里得到的是 Vue,而 $options._base 哪里来的?
// $options._base 在 /src/core/global-api/index.js 初始化函数 initGlobalAPI 中定义
// Vue.options._base = Vue
// 这里的 Vue.options 和 context.$options 连名字都不一样,这就是同一个东西?
// omg,options 和 $options 到底是怎么关联的?找吧
// 在文件 /src/core/instance/init.js 定义 _init 方法的时候有这样一个操作。。
/**
* // merge options —— 合并配置
* if (options && options._isComponent) {
* // optimize internal component instantiation
* // since dynamic options merging is pretty slow, and none of the
* // internal component options needs special treatment.
* initInternalComponent(vm, options)
* } else {
* vm.$options = mergeOptions(
* resolveConstructorOptions(vm.constructor),
* options || {},
* vm
* )
* }
**/
const baseCtor = context.$options._base
// plain options object: turn it into a constructor
// 构造子类构造函数
if (isObject(Ctor)) {
// 这里 baseCtor.extend 就等价于 Vue.extend()
// extend() 方法在哪里定义的?主要逻辑是干什么?
// /src/core/global-api/extend.js 文件中定义了方法 Vue.extend()
Ctor = baseCtor.extend(Ctor)
}
// if at this stage it's not a constructor or an async component factory,
// reject.
if (typeof Ctor !== 'function') {
if (process.env.NODE_ENV !== 'production') {
warn(`Invalid Component definition: ${String(Ctor)}`, context)
}
return
}
// async component
let asyncFactory
if (isUndef(Ctor.cid)) {
asyncFactory = Ctor
Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context)
if (Ctor === undefined) {
// return a placeholder node for async component, which is rendered
// as a comment node but preserves all the raw information for the node.
// the information will be used for async server-rendering and hydration.
return createAsyncPlaceholder(
asyncFactory,
data,
context,
children,
tag
)
}
}
data = data || {}
// resolve constructor options in case global mixins are applied after
// component constructor creation
resolveConstructorOptions(Ctor)
// transform component v-model data into props & events
if (isDef(data.model)) {
transformModel(Ctor.options, data)
}
// extract props
const propsData = extractPropsFromVNodeData(data, Ctor, tag)
// functional component
if (isTrue(Ctor.options.functional)) {
return createFunctionalComponent(Ctor, propsData, data, context, children)
}
// extract listeners, since these needs to be treated as
// child component listeners instead of DOM listeners
const listeners = data.on
// replace with listeners with .native modifier
// so it gets processed during parent component patch.
data.on = data.nativeOn
if (isTrue(Ctor.options.abstract)) {
// abstract components do not keep anything
// other than props & listeners & slot
// work around flow
const slot = data.slot
data = {}
if (slot) {
data.slot = slot
}
}
// install component management hooks onto the placeholder node
// 安装组件构造函数钩子
installComponentHooks(data)
// return a placeholder vnode
const name = Ctor.options.name || tag
// 实例化 VNode
const vnode = new VNode(
`vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
data, undefined, undefined, undefined, context,
{ Ctor, propsData, listeners, tag, children },
asyncFactory
)
// Weex specific: invoke recycle-list optimized @render function for
// extracting cell-slot template.
// https://github.com/Hanks10100/weex-native-directive/tree/master/component
/* istanbul ignore if */
if (__WEEX__ && isRecyclableComponent(vnode)) {
return renderRecyclableComponentTemplate(vnode)
}
return vnode
}这里有几部分比较重点,通过标注进行了解释,包括:构造子类构造函数、安装组件钩子函数、实例化 vnode;
Metadata
Metadata
Assignees
Labels
No labels