我们打开“src/core/vdom/patch.js”文件,代码如下:
function createElm ( vnode, insertedVnodeQueue, parentElm,refElm,nested,ownerArray,index ) { if (isDef(vnode.elm) && isDef(ownerArray)) { vnode = ownerArray[index] = cloneVNode(vnode) } // 是否为根元素插入 vnode.isRootInsert = !nested // for transition enter check // 如果是组件,直接 return if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) { return } // data属性 const data = vnode.data // 子集 const children = vnode.children // 标签名称 const tag = vnode.tag if (isDef(tag)) { if (process.env.NODE_ENV !== 'production') { if (data && data.pre) { creatingElmInVPre++ } if (isUnknownElement(vnode, creatingElmInVPre)) { warn( 'Unknown custom element: - did you ' + 'register the component correctly? For recursive components, ' + 'make sure to provide the "name" option.', vnode.context ) } } vnode.elm = vnode.ns ? nodeOps.createElementNS(vnode.ns, tag) : nodeOps.createElement(tag, vnode) setScope(vnode) /* istanbul ignore if */ if (__WEEX__) { // ... 省略部分weex平台代码 } else { createChildren(vnode, children, insertedVnodeQueue) if (isDef(data)) { invokeCreateHooks(vnode, insertedVnodeQueue) } insert(parentElm, vnode.elm, refElm) } if (process.env.NODE_ENV !== 'production' && data && data.pre) { creatingElmInVPre-- } } else if (isTrue(vnode.isComment)) { vnode.elm = nodeOps.createComment(vnode.text) insert(parentElm, vnode.elm, refElm) } else { vnode.elm = nodeOps.createTextNode(vnode.text) insert(parentElm, vnode.elm, refElm) } }
该函数主要是生成真实DOM元素,然后插入文档中,我们来拆分一下该函数。
if (isDef(vnode.elm) && isDef(ownerArray)) { vnode = ownerArray[index] = cloneVNode(vnode) }
如果 “vnode.elm” 存在,说明该vnode已被渲染过了。
"ownerArray" 参数主要是在新增 vnode 或者创建子集的时候存在。
// 是否为根元素插入vnode.isRootInsert = !nestedcif (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) { return}
根据 vnode 的 tag 字段创造真实的DOM元素。
调用该函数创建DOM元素:document.createElement(tagName)
createChildren(vnode, children, insertedVnodeQueue)
根据 children 元素生成DOM元素。
内部还是循环调用 createElement
invokeCreateHooks(vnode, insertedVnodeQueue)
调用创建钩子(create),或者插入钩子(insert)。
insert(parentElm, vnode.elm, refElm)
插入DOM元素。
调父级DOMd的appendChild方法插入vnode.elm
以上createElm函数的代码基本分析完了,如有错误欢迎指正,谢谢。