这篇博客其实主要不是为了实现diff算法,而是去为diff算法铺路。我们知道diff算法本质就是找不同,既然找不同,那前提一定是有可对比的东西(本篇博客的主要目的),那么接下来我们就进入正题。
学过react的朋友肯定都知道当jsx被编译的时候,它会被transform-react-jsx转译为相应的“东西”,这个“东西"实际上就是一个createElement方法。大致长相:
React.createElement('ul',null, React.createElement('li',null,'a'), React.createElement('li',null,'b') )参考地址:link
注意: 上面的代码仅仅表示jsx被转译后的样子。不是函数式组件或者class组件。函数式组件以及class组件是如何被编译的以及如何返回jsx的,我会在以后的博客里讲述的。
谷歌控制台显示如下:
一级展开: 二级展开: 最终展开:
在上面我们大致的实现了一个比较基础的vnode,既然vnode已经有了,那么下一步我们应该在相应浏览器的屏幕上将它展示出来。 展示的思路大致如下: vnode => 元素 实现过程:
/** * @method render * @params {Object} vnode * @params {Object} container * @description * 1、vode -- 虚拟DOM * 2、container -- 父容器(root or body) * 3、目的: 将vnode渲染在父容器中 * 4、实现思路: 递归 * 5、vnode可递归? vnode的每一个孩子都是Element即可。 * 6、具体细节: * 1、每次执行render方法,先获取元素类型。 * 2、遍历孩子节点(孩子节点是一定要有的,要不然创建一个空元素标签没有意义) * 判断每一个孩子节点的类型。 * 2.1、如果孩子节点是['xxx'],说明直接将孩子节点添加到父元素上。 * 2.2、如果孩子节点是[Element,Element,Element],说明孩子节点是一个子元素标签,从头开始遍历该方法。 * 3、遍历完孩子节点,退出循环,将其渲染到root or body上。 **/ function render(vnode,container){ var elementNode=document.createElement(vnode.tags) vnode.children.forEach((item)=>{ if(item instanceof Element){ var childNode=render(item,container) elementNode.appendChild(childNode) }else{ var textNode=document.createTextNode(item) elementNode.appendChild(textNode) return elementNode } }) container.appendChild(elementNode) return elementNode } // 测试用例(vnode在前面我们实现过了) render(vnode,document.getElementById('root')) <! DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>React极简实现</title> </head> <body> <div id='root'></div> <script src='./index.js'></script> </body> </html>测试结果如下:
其实render的实现涉及了一点递归算法,算法这个东西我各人认为和数学差不多,写多了练多了,灵感自然就来了。下一篇diff算法的真正实现马上就来喽。