Vue源码之createElement函数(五)

在render 函数中,最后调用的是createElement函数来返回vnode,那么createElement函数到底完成了什么功能

1. 首先看一下VNode的定义('src/core/vdom/vnode.js'),VNode被定义为一个类。

Vue源码之createElement函数(五)


2.  在createElement中,首先检测data的类型,通过判断data是不是数组,以及是不是基本类型,来判断data是否传入。如果没有传入,则将所有的参数向前赋值,且data=undifined。 

然后,判断判断传入的Normalize参数是否为真,为真的话,赋值给ALWAYS_NORMALIZE常量。

最后,再调用_createElement函数,可以看到,createElement是对参数做了一些处理以后,将其传给_createElement函数。

Vue源码之createElement函数(五)


3. 在_createElement中,首先判断data是不是响应式的,vnode中的data不能是响应式的。如果是,则Vue抛出警告

Vue源码之createElement函数(五)


4. 最重要的部分是将children拍平为单维数组。(‘src/core/vdom/helpers/normalize-children,js’)在simpleNormalizeChildren函数中,主要完成的功能是将children类数组的第一层转换为一个一维数组。

在normalizeChildren函数中,主要是调用normalizeArrayChildren函数去处理children类数组

Vue源码之createElement函数(五)


5. 在normalizeArrayChildren函数中,主要完成的功能是判断children中的元素是不是数组,如果是的话,就递归调用数组,并将每个元素保存在数组中返回。

首先判断children中的元素是不是数组,是的话递归调用函数。如果第一个和最后一个都是文本节点的话,将其合并,优化。

Vue源码之createElement函数(五)

然后,判断该元素是不是基本类型。如果是,在判断最后一个结点是不是文本节点,是的话将其与该元素合并为一个文本节点。否则,把这个基本类型转换为文本节点(VNode)

Vue源码之createElement函数(五)

最后一种情况,该元素是一个VNode,先同样进行优化(合并第一个和最后一个节点),然后判断该节点的属性,最后将该节点加入到结果中。

Vue源码之createElement函数(五)


6. 回到creat-element.js中,在将children拍平为一维数组后,接着判断标签(tag)是不是字符串,是的话,则判断该标签是不是平台内建的标签(如:‘div’),是的话则创建该VNode。

然后判断该标签是不是组件,是的话,创建一个组件VNode

如果都不是,则按照该标签名创建一个VNode。

Vue源码之createElement函数(五)

如果标签(tag)不是字符串,则创建组件VNode。

Vue源码之createElement函数(五)

至此,_createElement已经完成了创建VNode的功能,将其返回给render函数。


总结

createElement函数主要是通过对children进行扁平化处理之后,通过对标签(tag)的判断,使用VNode类来生成vnode,并将其返回。