方法开始生成真实的Dom, VNode 生成真实的Dom 的方式还是分为元素节点和组件两种方式,所以我们使用上一章生成的VNode分别说明 。
文章插图
1. 元素节点生成Dom
{// 元素节点VNodetag: 'div',children: [{tag: 'h1',children: [{text: 'title h1'}]}, {tag: 'h2',children: [{text: 'title h2'}]}, {tag: 'h3',children: [{text: 'title h3'}]}]}
大家可以先看下这个流程图有个印象即可,再接下来看具体实现时思路会清晰很多(这里先借用网上的一张图):
开始Dom, 来看下它的定义:
function createElm(vnode, insertedVnodeQueue, parentElm, refElm, nested, ownerArray, index) { ...const children = vnode.children// [VNode, VNode, VNode]const tag = vnode.tag// divif (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {return// 如果是组件结果返回true,不会继续,之后详解createComponent}if(isDef(tag)) {// 元素节点vnode.elm = nodeOps.createElement(tag)// 创建父节点createChildren(vnode, children, insertedVnodeQueue)// 创建子节点insert(parentElm, vnode.elm, refElm)// 插入} 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)// 插入到父节点}...}------------------------------------------------------------------nodeOps:export function createElement(tagName) {// 创建节点return document.createElement(tagName)}export function createComment(text) {//创建注释节点return document.createComment(text)}export function createTextNode(text) {// 创建文本节点return document.createTextNode(text)}function insert (parent, elm, ref) {//插入dom操作if (isDef(parent)) {// 有父节点if (isDef(ref)) { // 有参考节点if (ref.parentNode === parent) {// 参考节点的父节点等于传入的父节点nodeOps.insertBefore(parent, elm, ref)// 在父节点内的参考节点之前插入elm}} else {nodeOps.appendChild(parent, elm)//添加elm到parent内}}// 没有父节点什么都不做}这算一个比较重要的方法,因为很多地方会用到 。
依次判断是否是元素节点,注释节点,文本节点,分别创建它们然后插入到父节点里面,这里主要介绍创建元素节点,另外两个并没有复杂的逻辑 。我们接下来看下: 方法定义:
function createChild(vnode, children, insertedVnodeQueue) {if(Array.isArray(children)) {// 是数组for(let i = 0; i < children.length; ++i) {// 遍历vnode每一项createElm(// 递归调用children[i], insertedVnodeQueue, vnode.elm, null, true, // 不是根节点插入children, i)}} else if(isPrimitive(vnode.text)) {//typeof为string/number/symbol/boolean之一nodeOps.appendChild(// 创建并插入到父节点vnode.elm, nodeOps.createTextNode(String(vnode.text)))}}-------------------------------------------------------------------------------nodeOps:export default appendChild(node, child) {// 添加子节点node.appendChild(child)}
开始创建子节点,遍历VNode 的每一项,每一项还是使用之前的方法创建Dom 。如果某一项又是数组,继续调用创建某一项的子节点; 如果某一项不是数组,创建文本节点并将它添加到父节点内 。像这样使用递归的形式将嵌套的VNode全部创建为真实的Dom 。
在看一遍流程图,应该就能减少大家很多疑惑了(这里先借用网上一章图):
简单来说就是由里向外的挨个创建出真实的Dom, 然后插入到它的父节点内,最后将创建好的Dom插入到body内,完成创建的过程,元素节点的创建还是比较简单的,接下来看下组件式怎么创建的 。
- 【人工智能笔记】第五节:基于TensorFlow 2
- 揭秘历史上五大杀人不眨眼的特种作战部队
- 解析历史上的五阿哥永琪为什么没有当皇帝
- Spring MVC
- 风流乾隆:年寿最高的他一生中最宠爱哪五个女人
- 梁山不全是好汉:梁山五大庸才都有谁?
- 揭秘:三国历史上出身反贼的五大名将都是何人?
- 8051异步串口的收发原理
- 古代5件无价之宝,第五是慈禧夜明珠
- 吕后为何能以女子身份掌权长达十五年之久