React出身FaceBook豪门,一出生就带着virtualDOM和diff算法两大颠覆式的被动技能,很快引来高度关注,而且以高效快速著称。
通过一段时间的使用,抽出时间来学习其原理,发现并不难,可是想法很创新。造就了其不一样于传统框架的开发模式。html
VirtualDOM一直是React最著名,最神秘的特色。也是其高效迅速的核心。
virtualDOM其实很好理解:FaceBook的工程师认为传统的框架,频繁的操做DOM代价很大。性能和速度很低,想找一种东西替代DOM,但又能有DOM的嵌套结构和属性。因而FaceBook工程师们创造出virtualDOM。本质上virtualDOM就是一个json对象,用来描述真实DOM应有的属性和子集。拥有和DOM同样的嵌套关系造成的virtualDOM树。前端
举个例子:咱们有一段HTMLvue
<div id="wrap"> <div class="box1" style="margin-left: 10px;padding-top: 10px;"></div> <div class="box2"> <span data-name='box'>this is a box</span> </div> </div>
上述是一段很简单的有嵌套关系的HTML,咱们能够看到里面有几个关键属性,其实只须要记住这几个关键属性,咱们就至关于知道了整段节点。
根据上述HTML,抽象出来的该节点的关键属性。react
var conatiner = { tagName: 'div', id: 'wrap', children: [box1, box2] }; var box1 = { tagName: 'div', className: 'box1', style: {marginLeft: '10px', paddingTop: '10px'}, children: [] } var box2 = { tagName: 'div', className: 'box2', children: [text] }; var text = { tagName: 'span', 'data-name': 'box', // 自定义属性 text: 'this is a box' children: [] };
上面的HTML里面真正有用的信息仅仅几行代码就能够描述。React作的其实就是反向绘制。git
一个真实节点有不少属性,可是不少属性是绘制DOM相关的(好比offset,scrollTop这种,节点渲染以后添加的跟节点样式相关的属性)。virtualDOM对这些不常见属性暂不考虑(实际上这些绘制DOM的属性都在react-dom中),抽出重要的属性,以及嵌套关系记录下来(高效),放到内存中(迅速),这样减小了不少用不到的属性。 当virtualDOM树生成出来以后,只要按照特意的方法解析(JSX),就会快速的生成出DOM了。
以上大概就是React诞生的缘由和核心原理。github
另外一个著名的特色就是神秘的diff算法。这个算法也不难,甚至以为并不如宣传的那么牛*还有些失望。可是仍是比较麻烦的。
diff算法主要是用来判断两个virtualDOM树差别的,目的是以最小的代价去更新树。
当特定情境发生须要更改DOM的时候,React并不认为直接操做DOM是最好的选择。他认为不管是简单的DOM操做仍是复杂的DOM操做,都应由改动前的virtualDOM和改动后的virtualDOM计算出来,而后根据计算结果再去渲染DOM。这样至关因而计算出每次操做DOM的最优算法。
举个例子 须要移动火材棍使等式成立算法
图1-移动火材棍使等式成立示意图json
普通状况下你们直接将4个火材棍移到最前,两个火材棍移到中间,这样4-2=2等式成立。
聪明一点的人发现只须要移动中间的两个火材棍到最左,便可使等式成立。这样代价更小。
React通过计算发现:原来只须要移动"="的一个火材棍到"-"便可使等式成立2=4-2这样代价最小。
diff算法就是这样的一套标准化计算流程,其告诉React每次变化如何更改DOM代价最小,或者直接从新渲染性能最优。redux
React的另外一个创新思惟就是数据为中心。这也是现代前端框架广泛的思想。
如今渲染DOM也不用咱们来管了,操做DOM也不用咱们来管了那咱们来管什么?
咱们须要管理数据,告诉React什么使用,应该有什么样的DOM。
React是根据virtualDOM来渲染DOM的,那virtualDOM是根据什么生成的?答案就是state
React关键点就是state改变,就会从新渲染DOM,这样只须要将影响页面的数据放到state中。设置好什么时候如何触发修改state,剩下的React就会自动完成。数组
JSX能够说也是React的核心部分。它使用XML的标记方式直接去声明界面,组件界面间能够嵌套。
JSX最鲜明的特征就是,script标签中声明text属性为text/babel,这样调用babel解释器。
上面是官方的说法用通俗的话说就是:JSX其实就是一个为了使咱们方便使用React发明的一种转义工具。
包括在下面的例子中,咱们能够看到例子中的语法跟正常使用的语法不一样,就是由于babel。React原始的语法是不支持咱们如今使用组件嵌套的,好比down下React官方推荐的demo,第二个例子中的源代码以下:
图2-使用JSX语法编写示例
能够看到Counter组件的render方法return出了一个button组件。
若是打开React官方demo的第一个例子,会发现语法彻底不一样。
图3-使用React语法编写示例
能够看到原始的React语法是不支持组件嵌套的。甚至是不支持return <div><div>的。render方法return的只能是虚拟DOM。
React如何将用户输入的代码实现成真实DOM,是接下来要研究的问题。大体过程能够分为首次渲染和再次渲染。
图4-React渲染机制示意图
上图是整理出来的React渲染机制的流程图,左边的首次渲染的过程,右边是再次渲染的过程。这里主要讲解下该图。
咱们在使用React的时候,每每定义不少组件,组件输出的DOM中,还有自定义组件。
在JS最后,使用ReactDOM.render(element, container);将定义好的组到一个容器中。
咱们能够将首次渲染过程分为如下几步:
React首先对咱们定义组件进行解析 解析后的每一个组件的返回结果其实就是一个个virtualDOM 每一个virtualDOM中都会有children属性保存其子节点 这样根节点解析后 会产生一个完整的virtualDOM树。
React.render解析根节点virtualDOM 进而解析整个virtualDOM树(在React1.0以后 React拆分红React和React-dom 如今都使用ReactDOM.render)
React.render将virtualDOM传递给组件工厂 工厂断定virtualDOM具体类别进行具体解析 好比React将virtualDOM分为三类:文本节点 浏览器自带元素和自定义组件 每一个类的virtualDOM都有各自对应的component类进行解析 如上图
将每一个virtualDOM解析以后 调用各自component类的mountComponent方法 将virtualDOM翻译成真实DOM 并将其事件挂载到Document对象上
将整个virtualDOM翻译的真实DOM挂载到容器中
触发mount事件
这样就完成了首次渲染的逻辑,能够看到首次渲染的逻辑仍是比较简单,就是整理出定义的关键属性和嵌套关系成virtualDOM,按照virtualDOM进行绘制真实DOM,输出到挂载点上。
能够看一个简单的例子:
图5-React首次渲染实例-代码
图6-React首次渲染实例-显示
在上面的例子中咱们能够看到,定义了一个block和Box。React.createElement的第三个参数就是其子节点数组,box有三个block子节点和一个文本节点。最后将输出的DOM挂载到container上,显示如预期同样。咱们再来看看在此渲染的过程:
每次调用setState方法,都会调用该组件receiveComponent方法。
receiveComponent方法修改state而且判断,更改state后DOM是否发生修改,是的话diff算法实现最小更新。
渲染完成 调用hook函数componentDidUpdate。
这里再次渲染过程很简单,可是是最复杂的过程。每次渲染完成时virtualDOM树会继续保存在内存中, 在更改state等状况下直接使用。 三种不一样类型的节点,有着不一样的更改方法:好比文本节点直接替换 浏览器自带元素使用diff算法复杂计算。
React节点会有一个key属性,该属性就是React进行diff计算的。key上携带者嵌套,索引等相关信息。 diff算法中会递归找出virtualDOM树中的差异,组装成差别对象,添加到更新队列,在合适的时机进行更新。
以上就是React渲染机制的大体过程,至于diff算法这里暂不介绍,下面参考连接有详细介绍。
2013年React开源,做为目前较火的现代前端框架它有哪些优势和缺点,也是咱们能够了解。在众多框架中选型的重要参考。
目前较流行的框架有angular、vue等,下面横向做对比分析其优缺点。
Angular是09年google工程师建立的。做为划时代的前端框架,其创新性的使用指令系统和MVVM框架
优势:
丰富的指令系统,强大的指令系统是的开发者能够有不少方便的使用方法供选择;
较完善的MVVM框架,包含模板、路由、双向数据绑定、模块化、服务、过滤器、依赖注入等全部功能;
google去维护,用户数多,社区强大。
缺点:
太过繁杂的指令系统,提升了学习成本。
渲染速度太慢,有人作过测试以下图:
图中表示不一样框架每秒能渲染的操做数,越长表明性能越好。可见angular基本排在最后。
angular2对比angular1断崖式升级,对开发者形成很高的学习成本。
Vue是近些年最火爆的框架(国内)。尤为在做者尤大加入到阿里后,vue在国内的影响力和推广力更强。
优势:
渲染效率差很少是React的10倍;
结合Angular和React的优势,有模板、有virtualDOM、有过滤器和指令系统。上手简单,十分方便。
缺点:
新生儿。做者16加入阿里,维护和社区方面跟其余两个框架比,不是很强大。
不支持IE8。(??什么是IE8??)
主角来了。通过几年的发展,你们的实践,React也是愈来愈完善。不断推出的React邪教全家桶(router redux RN等)也是渐渐丰富了React的生态。
优势:
思想新颖,影响了vue等框架;
FaceBook是他亲爹,不少大型项目都在用,完善的维护和强大的社区(国外各类追捧)。
缺点:
新颖的思惟,形成了其须要理解实现过程,上手成本较高;
对动画效果支持不是很好;
不是MV框架,只负责UI绘制须要学习全家桶来实现MV框架。