为了得到更好的阅读体验,请访问原地址: 传送门
React 是一个起源于 Facebook 的内部项目,由于当时 Facebook 对于市场上全部的 JavaScript MVC 框架都不太满意,因此索性就本身写了一套,用来架设 Instagram。作出来以后,发现这套东西还蛮好用的,因而就在 2013 年 5 月开源了。html
在这里咱们须要稍微注意一下 库(Library) 和 框架(Framework) 的区别,React 自己是一个用于构建用户界面的 JavaScript 库,而咱们平时所说的 React 框架实际上是指的是 React/ React-router 和 React-redux 的结合体,库和框架的本质区别体如今于控制权:前端
这是一个很是有趣的问题,也让我困惑和苦恼。在笔者还在学校的时候尝试用 Vue 搭建了一套简单的博客系统,学习曲线平滑,让只会一些基础 HTML/ CSS 代码的我经过一段时间学习就可以上手了,可是学习 React 以来,进展变得相对缓慢.. 一部分缘由是由于 React 创新性的开发模式以及让我感到无所适从的 JSX 语法(菜才是原罪)。react
Vue 做者尤雨溪在知乎上回答「Vue 和 React 的优势分别是什么?」这个问题的时候提到 :git
这里我能够大方地认可,若是多年之后要论历史地位,React 确定是高于 Vue 的。事实上,我做为一个开发者,也是由衷地佩服 Jordan Walke, Sebastian Markbage 这样的,能从开发模式层面上提出突破性的新方向的人。React 从一开始的定位就是提出 UI 开发的新思路。当年 Pete Hunt 最开始推广 React 的时候的一句口号就叫 "Rethinking Best Practices",这样的定位使得 React 打开了一些全新的思路,吸引了一群喜欢折腾的早期核心用户,并在这个基础上经过社区迭代孵化出了许多今天被 React 开发者看成常识的 pattern。这是 React 伟大的地方,Vue 里面也有不少地方是直接受到了 React 的启发。React 敢作这样的尝试,是由于它是 Facebook。这样的体量的公司,在 infrastructure 层面得到质的提高,收益是巨大的,并且 Facebook 的工程师们足够聪明又要靠工资吃饭,改变他/她们的习惯并非什么问题。而对外推广,则是一种大公司才有的 “改变业界” 的底气。github
相比「为何使用 React?」的理由,称赞 React 的却是明显更多一些(React 确实是突破性的开发模式)。算法
是由于 React 组件化的思想吗?不是。我以为这跟多少跟微服务化之类的概念有点儿相似,这是属于一个时代对于计算机工程的思想进步,是对于团队协做提出的新一种成熟的解决方案,也是必然的一种趋势。当前流行的无论是 Angular/ Vue 仍是 React,都自然的支持着组件化的概念。shell
那是由于 React 性能出众吗?我想也不是。或许 React 刚出世时由于其独特高效的虚拟 DOM 设计,可以在前端江湖中平步青云,可是如今前端技术都主键地趋于成熟(我也不懂,我乱说的..),从不少地方的对比数据中,都可以看获得其实 React 与其余框架的性能差别并非特别大。而且体如今平时的开发中,这样对比不明显的速度差别,根本没有多大的用处。编程
还看到一种观点,说 React 适用于构建大型的项目。从我并很少的了解中,我知道 React 体系中自然有着许多的约束,以及一些不成文的约定,这就好像是 SpringBoot 中默认提供给使用者的一些姿式,自然就有很强的工程性,加上一些约定俗成的代码风格 or 归约,这就使得 Java 很适合一些大型的团队项目。但能不能开发大型的项目历来都是取决于人,而不是采用了哪一种框架。redux
因此比较令我信服的理由是(我乱猜的):像 Java 同样,React 体系足够成熟,社区也很是活跃,你遇到的问题很容易在网络上找到答案,而且也有一些成熟的实践 or 轮子用以解决各类各样的问题。并且 React 还有一个比较特别的特性是:你可以比较无痛地使用 React Native 开发原生移动应用。数组
要理解这个「虚拟 DOM」的概念,首先咱们就须要知道什么是「DOM」。咱们先暂时忘掉什么网页之类的,咱们想象如今咱们须要编写程序来对下列的 Markdown 文档进行改变应该怎么作:
# Title ## subtitle - 1 content - 1 ## subtitle - 2 content - 2
好比我如今就想要 content - 2
的内容进行改变,那么我就须要一行一行的不断遍历直到最后遍历到它才能进行操做,对内容改变的操做都差很少,因此若是我想对这个查找的操做进行优化,最简单的想法就是把它树化以减小高度,增长效率。
DOM 是英文 Document Object Model 的缩写,即文档对象模型。它是一种跨平台的、独立于编程语言的 API,它把 HTML、XHTML 或 XML 文档都当作一个树结构,而每一个节点视为一个对象,这些对象能够被编程语言操做,进而改变文档的结构,映射到文档的显示。DOM 最开始的时候是和 JavaScript 交织在一块儿的,只是后来它们最终演变成了两个独立的实体。DOM 被设计成与特定编程语言相独立,尽管绝大部分时候咱们都是使用 JavaScript 来操做,但其实其余的语言同样能够(如 Python)。
假若有这么一段 HTML 代码:
<html> <head> <title>文档标题</title> </head> <body> <a href="">连接</a> <h1>标题</h1> </body> </html>
那么它最终就应该会是下面这棵树同样的结构:
这里不对 DOM 节点的类型啊方法之类的进行讨论,咱们只须要对 DOM 有一个大体的概念就行了。
咱们能够简单了解一下浏览器渲染 DOM 的流程:
其实严格来讲,单纯的操做 DOM 并不慢,说它慢是带有必定条件的。
想象在一次事件循环中屡次操做 DOM 时,有时但愿 JS 代码中能马上获取最新的 DOM 节点信息,这时浏览器不得不挂起 JS 引擎,转而调用 DOM 引擎,计算渲染出最新的 DOM,以此来获取最新的 DOM 节点信息,接着再从新激活 JS 引擎 继续后续的操做。
能够预见,上述操做不只须要屡次进行引擎的切换,还须要屡次计算布局,从新绘制 DOM。事实上paint
是一个耗时的过程,然而layout
是一个更耗时的过程,咱们没法肯定layout
必定是自上而下或是自下而上进行的,甚至一次layout
会牵涉到整个文档布局的从新计算。
可是layout
是确定没法避免的,因此咱们主要是要最小化layout
的次数。
因此,下降引擎切换频率、减少 DOM 变动规模才是 DOM 性能优化方案的关键!
虚拟 DOM 正是解决了上述问题,它的本质就是用 JS 对象来模拟出咱们真实的 DOM 树,它的算法大体以下:
咱们由此能够对比出二者的不一样:
使用虚拟DOM的损耗计算:
总损耗 = 虚拟DOM增删改 + (与Diff算法效率有关)真实DOM差别增删改 + (较少的节点)排版与重绘
直接使用真实DOM的损耗计算:
总损耗 = 真实DOM彻底增删改 + (可能较多的节点)排版与重绘
虚拟 DOM 的核心在于 Diff,它自动帮你计算那些应该调整的,而后只修改应该被调整的区域,省下的不是运行速度这种 "小速度",而是开发速度/ 维护速度/ 逻辑简练程度等 "整体速度"。
但虚拟 DOM 快也是在相对条件下的,这里引用 @尤雨溪
大大在知乎问题《网上都说操做真实 DOM 慢,但测试结果却比 React 更快,为何?》上回答的一句话吧:
不要天真地觉得 Virtual DOM 就是快,diff 不是免费的,batching 么 MVVM 也能作,并且最终 patch 的时候还不是要用原生 API。在我看来 Virtual DOM 真正的价值历来都不是性能,而是它 1) 为函数式的 UI 编程方式打开了大门;2) 能够渲染到 DOM 之外的 backend,好比 ReactNative。
Diff 大体能够分为三种类型:
Component Diff: 在进行 Tree Diff 的时候,每一层中,组件级别的对比,叫作 Component Diff:
使用 React 的网页源码,结构大体以下(能够直接运行):
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>Hello React!</title> <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script> <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script> <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') ); </script> </body> </html>
上面代码有两个地方须要注意。首先,最后一个 <script>
标签的 type
属性为 text/babel
。这是由于 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel"
。
其次,上面代码一共用了三个库: react.js
、react-dom.js
和 Browser.js
,它们必须首先加载。其中,react.js
是 React 的核心库,react-dom.js
是提供与 DOM 相关的功能,Browser.js
的做用是将 JSX 语法转为 JavaScript 语法,这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。
$ babel src --out-dir build
上面命令能够将 src
子目录的 js
文件进行语法转换,转码后的文件所有放在 build
子目录。
ReactDOM.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。
ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') );
上面代码将一个 h1
标题,插入 example
节点,运行结果以下:
上一节的代码, HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它容许 HTML 与 JavaScript 的混写。咱们先来看如下一段代码:
const element = <h1>Hello, world!</h1>;
与浏览器的 DOM 元素不一样,React 当中的元素事实上是普通的对象,React DOM 能够确保 浏览器 DOM 的数据内容与 React 元素保持一致。要将 React 元素渲染到根 DOM 节点中,咱们经过把它们都传递给 ReactDOM.render() 的方法来将其渲染到页面上:
var myDivElement = <div className="foo" />; ReactDOM.render(myDivElement, document.getElementById('example'));
JSX 看起来相似 HTML ,你也能够在上面代码中嵌套多个 HTML 标签,可是须要使用一个 div
元素包裹它。
咱们能够在 JSX 中使用 JavaScript 表达式。表达式写在花括号 {} 中。实例以下:
ReactDOM.render( <div> <h1>{1+1}</h1> </div> , document.getElementById('example') );
在 JSX 中不能使用 if else 语句,但可使用 conditional (三元运算) 表达式来替代。如下实例中若是变量 i 等于 1 浏览器将输出 true, 若是修改 i 的值,则会输出 false.
ReactDOM.render( <div> <h1>{i == 1 ? 'True!' : 'False'}</h1> </div> , document.getElementById('example') );
React 推荐使用内联样式。咱们可使用 camelCase 语法来设置内联样式. React 会在指定元素数字后自动添加 px 。如下实例演示了为 h1 元素添加 myStyle 内联样式:
var myStyle = { fontSize: 100, color: '#FF0000' }; ReactDOM.render( <h1 style = {myStyle}>菜鸟教程</h1>, document.getElementById('example') );
注释须要写在花括号中,实例以下:
ReactDOM.render( <div> <h1>菜鸟教程</h1> {/*注释...*/} </div>, document.getElementById('example') );
JSX 容许在模板中插入数组,数组会自动展开全部成员:
var arr = [ <h1>菜鸟教程</h1>, <h2>学的不只是技术,更是梦想!</h2>, ]; ReactDOM.render( <div>{arr}</div>, document.getElementById('example') );
按照惯例黏一个尾巴:
欢迎转载,转载请注明出处!
独立域名博客:wmyskxz.com
简书ID: @我没有三颗心脏
github: wmyskxz
欢迎关注公众微信号:wmyskxz
分享本身的学习 & 学习资料 & 生活
想要交流的朋友也能够加qq群:3382693
钱
本文由博客一文多发平台 OpenWrite 发布!