diff算法(一)之对比元素的创建

tech2022-08-07  142

从0实现Diff算法(一)

一、文章概述

这篇博客其实主要不是为了实现diff算法,而是去为diff算法铺路。我们知道diff算法本质就是找不同,既然找不同,那前提一定是有可对比的东西(本篇博客的主要目的),那么接下来我们就进入正题。

二、createElement概述

学过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的,我会在以后的博客里讲述的。

三、实现一个createElement

/** * @author xiaojiujiu 2020-09-02 * @method createElement * @params {String} tags * @params {Object} props * @params {Array} children * @description * tags: 元素的类型 * props:元素的属性 * children: 子元素或者文本节点 * @return * 返回一个虚拟DOM(其实就是js对象,也可以叫做N叉树) **/ function createElement(tags,props,children){ return new Element(tags,props,children) } /** * @method Element * @params {String} tags * @params {Object} props * @parmas {Array} children * @description * 一个js类,用于创建vnode **/ class Element(tags,props,children){ constructor(tags,props,children){ this.tags=tags this.props=props this.children=children } } var vnode=createElement('ul',{class:'ul'},[ createElement('li',{class:'li1'},['a']), createElement('li',{class:'li2'},['b']), createElement('li',{class:'li3'},['c']) ]) console.log(vnode) // 测试一下

谷歌控制台显示如下:

一级展开: 二级展开: 最终展开:

四、实现一个render方法

在上面我们大致的实现了一个比较基础的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算法的真正实现马上就来喽。

最新回复(0)