准备工作
虚拟DOM是一种轻量级的JS对象,包含以下属性:
- tag:标签名
- attrs:属性,一般有id class name等等
- children:子节点的标签名属性子节点等…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| const vnode = { tag:'DIV', attrs: { id: 'app', }, children: [ { tag: 'SPAN', children: [ {tag: 'A', children: []} ], },{ tag: 'SPAN', children: [ {tag: 'A', children: []}, {tag: 'A', children: []}, ], } ] }
<div id = 'app'> <span><a></a></span> <span> <a></a> <a></a> </span> </div>
|
实现思路
- 获取父节点的tag属性,通过document.createElement生成节点
- 若有属性,则通过setAttrubite(key, value)添加属性
- 如有子节点,则遍历子节点,重复步骤1,2
- 把子节点通过appendChild添加到父节点
注意:最后会遇到节点为文本的情况,则可以通过createTextNode方式转义HTML字符,如果是number,可以先转换成string
JS实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| function myRender(vnode) { if (typeof vnode === 'number') { vnode = String(vnode); } if (typeof vnode === 'string') { return document.createTextNode(vnode); } let dom = document.createElement(vnode.tag); if (vnode.attrs) { for (let key of vnode.attrs) { dom.setAttribute(key, vnode.attrs[key]); } } if (vnode.children.length) { vnode.children((child) => dom.appendChild(myRender(child))); } return dom; }
|