1、ReactJS的背景
1、react是Facebook为实现其内部广告系统项目设计的一种前端界面构建方式
2、前端工程师的职责就是把逻辑数据实时反应到view层,既然涉及到vie层,
那就涉及到dom树。而大家都知道,复杂或者频繁的操作dom通常是造成性能
不好的地方。
3、所以设计react的地方就是其虚拟dom
2、ReactJS的设计原理
react的设计原理就是其引入的虚拟dom机制:
1、react用javascript在浏览器端实现了一套虚拟dom api。
2、基于react开发的时候所有的dom构造都是基于虚拟dom进行的
3、每当有state更改的时候,react就重新render一整套虚拟dom树,
react机制会将当前的整个dom树和上一次的dom树进行对比
取到diff,进行真实的dom更改。
4、其实state也有一部分实现的是数据、html片段绑定,
直接更新的数据是包含的
其实说到这里,往深一点考虑就是react的虚拟dom的diff算法
从大层面上来讲
![react数据驱动更新dom树](https://i-blog.csdnimg.cn/blog_migrate/713d83758d0536b1c15a95a574b27482.png)
深层次一点就是react的diff算法是怎么理解的。
错误的见解:我曾经以为diff算法,就是深层次的diff,算法运算时只比较
不同的。但其实当时浅显的想法,确实是diff运算的结果,但不是
diff运算的算法。
1、tree diff
也叫层级diff,
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/bea72e360fe662a1537c50ff34495526.jpeg)
针对上图
React对Virtual DOM树进行层级控制,只会对相同层级的DOM节点进行比
较,即同一个父元素下的所有子节点,当发现节点已经不存在了,则会删除掉
该节点下所有的子节点,不会再进行比较。这样只需要对DOM树进行一次遍
历,就可以完成整个树的比较。
即使说a节点以及他的子节点被移动,但是react只关注同级比较,在第二层
把a及其子节点删了,在第三层再重新创建,所以diff运算量大,影响性能
不建议setState直接更改树的结构。最好是state颗粒度小,只改变树中
的某一个小的节点,那么diff的时候只会深度比较这一个小节点。
2、componnet diff
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/09095edf012e3b430b6b5bd65e6ea2d0.jpeg)
假如说因为某个条件切换,所以要显示不同的组件。
1、比较两个组件的类型(D和G)
2、如果(D和G)不是同一类型,进行diff算法,分析会影响性能
直接删掉上一个虚拟dom组件。 重新创建新的组件。
如果是同一类型的组件,会按照层级策略深层对比每个节点。
3、element diff
精确的对属于同一层级的节点diff时,提供了3种节点操作,分别为INSERT_MARKUP(插入),MOVE_EXISTING(移动),REMOVE_NODE(删除)。
如果同一层级,没有这个新节点会新增插入
如果同一层级,如果有新节点,但是属性不一样,会复用节点,赋值属性
如果同一层次,旧dom有,新dom没有,会删除这个节点。
总结:setState()触发一次组件重绘,其实就是虚拟dom重新生成,除非在
shouldComponentUpdate()中实现了一些条件渲染逻辑。来允许和阻止是否需要
调用指定组件的 render 方法。其实这个深入逻辑就是他触发了render,只是是
否触发了内部的diff算法,return false 的时候,不diff,render出来的新
旧dom一样。diff算法的复杂度为0。
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/bfd6d03ca4cbf596bca18c380649311b.png)
React的核心
1、使用组件定义界面,是一个View层的前端库,界面可能由
一个或者多个组件构建而成
react的虚拟DOM是如何反映到真实的DOM树上的?
解答:首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比
innerHTML插入慢。虚拟DOM可以确保只对界面上真正变化的部分进行
实际的DOM操作。
比如:
替换节点就需要调原生JS对象的repaceChild()接口;
对于修改属性,则要调setAttribute()接口等等。
3、react 生命周期
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/03384c3f4a91228e07102139e914245a.jpeg)