React 理解 及 与其它框架区别
文章目录
在 React 下,我们需要考虑的,是每个组件在任意一个状态下应该怎么渲染。
(状态就是数据)
React 会把这些组件装配成页面。
然后当数据更新后, React 又把新数据传给组件,于是又根据新数据重新渲染
React 把重新渲染的结果和之前渲染的结果进行比对,找出需要更新的部分,进行更新。
我们只需要正确的更新数据/状态,不必再在渲染时考虑数据发生了什么变化(例如是增加了一条记录还是减少了一条记录?增加到什么位置?不需要考虑这些也就不需要考虑我们在进行 DOM 操作时插入到哪里等问题)。
我们只需要指定好规则(即给出任意一种状态,这个组件应该怎么渲染),并正确的更新状态,这些组件就会重新渲染。
这两种模式(状态更新时重新渲染完整页面、自动化的 DOM 原子操作)不是偶然组合到一起的。
每次都重新渲染页面不需要自动化 DOM 操作也可以实现(不过效率较低)
传统网站的模式是状态更新时重新渲染完整页面(对程序员友好。性能不好(两方面:1. 网络传输量大 2. 渲染页面成本高))
AJAX 的模式是不重新渲染,而是只更新必要的部分(性能好)
还有一些模式是在前端重新渲染完整页面,因此解决了模式1性能问题的一半
(即对程序员友好,但页面渲染成本高。此外,这种模式下需要分别在后端和前端对数据进行两次修改)
模式1就不加入对比了,这里考虑模式2和3。有没有什么办法让模式2对程序员友好?有没有什么办法让模式3的效率提高?
对于模式2暂时没有想到解法,也就是既要手动指定要更新的部分,又不那么复杂、容易出错。
而对于模式3的优化,也就是现在 AngularJS 和 React 做的:把模式3的底层转换成模式2的模式。
模式2和模式3在本质上究竟有哪些区别?
AngularJS 和 React 难道都是一样的模式?
是否都是只需要考虑界面在当前状态下如何渲染,但最终更新页面时只更新必要的部分?
AngularJS 的 Directive 貌似不完全是这样? 是否 React 比 AngularJS 更纯粹直接一点?
自动检查需要更新哪些 DOM 这样的模式是否必须配合指定渲染规则每次重新渲染的模式一起使用?
如果是,那么 AngularJS 应该就是和 React 一样的模式?
不过 AngularJS 还有数据绑定等特点,这些和 React 究竟有哪些区别?
理解 React
Web 前端的几种运行模式
第一种:静态网页
完全由后端输出网页,需要更新时,便刷新页面
第二种: AJAX + DOM
通过 AJAX 与后台交互,并实现页面内容的动态更新。
这种应用里大部分时间都在处理 AJAX 请求和执行 DOM 操作,
因此出现了如 jQuery 这类辅助工具或框架
第三种:自动化 DOM 操作
一般通过现成的类库(如 AngularJS, Kncokout, React...)来实现。
这些类库可以以某种形式把页面内容与 JS 数据绑定在一起,
当 JS 数据更新时,就会自动更新页面内容,省去了手动操作 DOM 的繁琐过程。
React 与传统前端框架/工具的对比
React 与 AngularJS 的对比
AngularJS 的模式与 React 有什么异同,它们为什么会各自演变成现在的模式?
AngularJS 的模式:
Directive 指令式地定义界面
|- Controller 业务逻辑,负责维护 Model
|- Model 业务数据,可看作 Directive 当前的状态
|- Link 维护视图,用户实际生成用户界面
Directive 可以嵌套使用
React 是由你自己随意组织页面,更灵活,更容易理解和学习
它把 JS 和 HTML 有机地组合到了一起,使得可以像操作 JS object 一样,操作 HTML 元素。
灵活 是因为没有 Ng 哪些现成的 directive 的限制。
不用按照规定好了的模式去组织页面,想怎么组织就怎么组织。
容易理解 是因为我们只要把 HTML 看成一种 JS Object 就行了。就像平常一样把它们放进数组,传给其他函数或返回。不像 Ng ,必须理解它的运作机制:双向绑定,Directive,Scope... 不然你很难进行使用,碰到了问题也不知道该怎么处理。
而且 React 中的操作、页面渲染都由用户自己通过 JS 来完成,就不用去学习 ng 中那么多 directive 每一个的用法了。
而且 React 因为概念简单,所写的完全就是普通的 JS,平常用到的 timeout,AJAX 等操作都照常使用,与 React 互不影响,类库也不会互相冲突。而 AngularJS 则包含了太多自己独创的概念,使得浏览器原生的很多操作(如 timeout,AJAX)都不能直接完成,而要加一个包裹层,各种类库往往也不能直接使用,要注意与 Angular 的互相抵触。这就要求用户要学习如何使用这些东西,并在工作中处处留心,别一不小心忘了遵守 AngularJS 的某些要求,写出有 bug 的代码。(例如习惯性的用了 tiemout,而没用 $timeout 就有可能造成潜在的 bug 或是让页面显示出现不正常)
Angular 和 Knockout 中,界面定义和业务逻辑处理通常分散在两个文件中(controller + HTML)
但 HTML 中也难免夹杂一些业务逻辑,JS 文件中,有时也要带上点界面操作。因此两文件中都分别有界面部分和逻辑部分,比较零散、混乱。
而 React 中,界面定义和逻辑处理都通过 JS 来完成(但并不是混在一起,而是互相区分的),所以都放在同一个文件里,这样更直观。出问题时也好排查。在 ng 中,经常出现想看看一个小行为是怎么实现的,结果找了半天也找不到实现它的那段代码的问题。
React 的函数式与 VDOM
React 为什么使用不可变 state
State 与不可变的优点(不可变是指不能直接修改 state 对象,但可用另一个对象代替它,以进入另一个状态):
没调用一次 setState,可以同时提交奥多处改动。
试想,如歌 state 是可变的,那么:
我们要么是用 Angualr 那样的模式:state.abc = "def"
但这就需要实现一个复杂的 watcher,而且当数据量很大时,会遇到性能瓶颈。
要么使用 knockout 的模式:state.abc("def")
但这样每更新一条数据,knockout 就要重新计算一次最新的页面内容,性能也不行。
React 为什么用 VDOM 的形式进行页面更新
state 更新后(包含了多条数据的值的更新),
React 有几种选择:
用新 state 渲染出一个新页面,直接写入浏览器,替换原来的页面(性能很差)
找出新老 state 的区别,对现有页面进行 DOM 操作,使其符合新 state。
(性能好,相对上一种方法,减少了许多不必要的 DOM 操作)
用新 state 渲染出一个新的虚拟界面(VDOM)。找出虚拟页面与当前页面的不同之处(实际上并不会和真实的页面进行对比,而是和上一版的 VDOM 进行对比,React 对上一版的 VDOM 进行了缓存,这样能有更好的性能,也更容易实现),并更新这些不同的地方。
(性能更好,进一步减少了 DOM 操作,而且不用对数据与 DOM 节点间的关系进行记录和分析)
第二种方法就类似 Angular 的方法,而第三种则是 React 现在的方法。那么为什么第三种所需的 DOM 操作会比第二种少呢?
下面以把一个数组渲染为