vue使用createElement函数创建vnode
上文中我们提到了vue使用虚拟dom来描述dom节点,这样做的目的是较少浏览器的开销,提高性能。那么vue是如何创建虚拟dom的呢?下面我们来分析vue中的createElement函数是如何创建vnode的。
createElement 函数定义在src\core\vdom\create-element.js 文件中
export function createElement (
context: Component,
tag: any,
data: any,
children: any,
normalizationType: any,
alwaysNormalize: boolean
): VNode | Array<VNode> {
if (Array.isArray(data) || isPrimitive(data)) {
normalizationType = children
children = data
data = undefined
}
if (isTrue(alwaysNormalize)) {
normalizationType = ALWAYS_NORMALIZE
}
return _createElement(context, tag, data, children, normalizationType)
}
createElement 函数是对_createElement函数的封装,_createElment函数才是真正创建vnode的函数。createElement 对传入的参数进行了处理,这使得传入的参数更加灵活。这其实也是我们需要学习的封装技巧,将一些参数的边界处理,或者其他情况提取成一个外部使用函数,而真正处理逻辑的函数只需要关注核心部分即可。
_createElment定义如下:
export function _createElement (
context: Component,
tag?: string | Class<Component> | Function | Object,
data?: VNodeData,
children?: any,
normalizationType?: number
): VNode | Array<VNode> {
if (isDef(data) && isDef((data: any).__ob__)) {
process.env.NODE_ENV !== 'production' && warn(
`Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` +
'Always create fresh vnode data objects in each render!',
context
)
return createEmptyVNode()
}
// object syntax in v-bind
if (isDef(data) && isDef(data.is)) {
tag = data.is
}
if (!tag) {
// in case of component :is set to falsy value
return createEmptyVNode()
}
// warn against non-primitive key
if (process.env.NODE_ENV !== 'produ