什么是React?

129 阅读12分钟

React是一个用于实现Web前端的库。它仅覆盖视图层,也就是用户界面的显示。至于业务代码逻辑的结构和其他架构关系,React不提供具体的规定,这使得前端设计在React中比其他框架和库具有更高的自由度。这种自由度的缺点是,特别对于初学者来说,学习如何使用React以及如何合理地构建大型应用程序可能会比较困难。这种相对较高的入门门槛和陡峭的学习曲线也是对React的主要批评点之一。然而,学习初期的额外投入很快会在开发中得到回报。React项目的官方网站提供了大量更深层次的信息和教程,网址是react.dev。

借助像Create React App这样的工具,可以极大地简化React的入门过程。与许多其他JavaScript库和框架一样,React是一个开源项目。其开发者选择了MIT开源许可证,这种许可证非常宽松的,允许将项目用于私人和商业用途,只要求注明许可证和版权,并排除了任何责任。项目的源代码托管在GitHub上,并以NPM包的形式提供。NPM是目前全球最大的包管理器,几乎所有JavaScript项目都使用它,它提供了一个公共仓库和一个命令行工具用于包管理。

React的开发初衷之一是使库能够在多个平台上使用。这种方法也解释了为什么React库被划分为多个包。因此,像Renderer(渲染器)这样的平台特定组件(负责渲染应用程序)可以被替换,而其他结构则保持不变。在本章中,你将会更详细地了解React的两个关键部分:Renderer和Reconciler(渲染器算法),Reconciler算法负责查找应用程序前后状态之间的差异,Renderer实现更加高效的应用程序渲染。

单页面应用程序

通常,你会使用React来实现单页面应用程序。单页面应用程序的核心概念是,当需要显示应用程序的新状态时,浏览器不需要完全重新加载应用程序。这也解释了“单页面”的名称,因为应用程序基本上只包含一个HTML页面。这个页面通过JavaScript自定义,用于反映应用程序的当前状态。然而,这种类型的Web应用程序有一个缺点,即初始加载过程比传统网站要长得多。原因是需要加载渲染应用程序所需的所有资源。不过,这个问题已经有了解决方案,例如懒加载和服务器端渲染,稍后你将在本书中了解这些解决方案。

对于Web应用程序的用户来说,单页面应用程序比多页面应用程序更为便利。在多页面应用程序中,每次页面切换时都必须重新加载单独的视图,而单页面应用程序的过渡可以设计得更加流畅。在React应用程序中,除非在特殊情况下,否则多页面架构不是常见的选择,因为每次加载时都必须加载整个React源代码。这个问题可以通过使用浏览器缓存来最小化,这样只有第一次加载过程会更长,后续加载则会更快。然而,在加载完源代码后,React还需要执行并构建应用程序的可视结构。

此外,浏览器中的重新加载会导致当前应用程序的状态在前端被丢弃,然后需要重新构建。对于React应用程序来说,这意味着所有组件的状态需要存储在服务器端或浏览器的Web存储中。在单页面应用程序中,应用程序的状态在浏览器会话期间得以保留,你可以访问内存中的内容并在其中存放对象。

React利用单页面应用程序的特点来提升性能,使得Web应用程序的体验类似于原生应用程序。然而,在React达到今天的优化水平之前,这个库经历了大量的改进和增强。

React的历史

与其竞争对手Angular相比,如果看一下React的最初版本,React的发布时间处于中间位置。Angular的第一个版本发布于2009年;Vue.js发布于2014年。React从2011年起就被应用于Facebook开发,并且自那时起,经历了丰富的历史。最初,React被用于Facebook平台的核心元素开发,即新消息推送。然后在2012年,React被应用到了Instagram,而Instagram被Meta收购。Instagram选择使用React也对库的抽象化做出了重要贡献。

React的崛起

React的历史始于2011年,当时名为FaxJS。JordanWalke使用这个库开发了React的原型。FaxJS的一个主要特性是能够实现无缝的渲染,无论应用运行在服务器上还是在用户的浏览器上,都能提供一致的渲染体验。此外,即使在FaxJS的早期版本中也已经具备了这种环境独立的特性,React的渲染机制不依赖于特定的运行环境。此外,响应性也起着重要作用。当应用程序的数据发生变化时,前端应该自动适应。快速内容渲染和低加载时间是FaxJS的另一个特点。与React类似,这个库采用面向组件的声明式方法来构建图形应用程序。FaxJS的灵感则来自HTML组件框架XHP。

2015年,除支持浏览器外,React还支持移动平台的原生应用程序开发: React Native。

从0.x版本到15版本的飞跃

React遵循语义版本控制的方法,也就是软件的版本由三个数字组成:主版本号、次版本号和补丁级别。

React长期以来以0.x版本进行次要更新,这种做法在开源项目中非常普遍,通常用于表明项目仍处于早期阶段。在此阶段,即使是小版本更新(次版本号增加)也可能会引入突破性的改动,而根据语义版本控制的原则,这种改动通常只会在主版本更新时发生。总体而言,0.x版本象征着有限的稳定性。这种方法在其他项目(如Node.js)中已被证明是成功的。React之所以从0.x版本直接跳转到主要版本(如React15版),是为了向用户传达一个信号,即该项目已经达到了完全成熟,并且可以稳定地用于实际项目开发的阶段**。**

Meta公司一直在Facebook平台上使用React进行开发。因此,React的新版本通常会在正式发布之前,先用于Facebook平台的开发,以确保新版本已经经过实际环境的测试。React直接跳跃到第15版本,旨在进一步强调React新版本已经在生产系统中得到了长期使用和验证。

2016年4月,React向版本15迁移后,React本身也发生了一些重大变化。例如,取消了对InternetExplorer8的支持。引入了请求评论(RFCs)的方法,使得开发过程变得更加透明。自引入这一开发过程以来,对React的变更或变更请求都会以RFC形式发布并供社区开发者讨论。这些RFC可以在GitHub上找到,地址是github.com/reactjs/rfc…

React15中最重要的技术创新是显著地改进了对浏览器DOM的处理。从这个版本开始,使用createElement方法取代了之前使用的innerHTML方法。此外,还删除了将文本包裹在span元素中的需要,并完成了对可缩放矢量图形(SVG)的支持。

再一次重大飞跃

长期以来,React社区一直热切期待着这个版本的发布。该版本的核心是新的Fiber调节器(Fiberreconciler)。调和器是用于计算先前界面状态和新界面状态之间差异的算法。Fiber的引入不仅显著提高了React的性能,更重要的是,它为未来的开发和新功能铺平了道路。由于堆栈调和器已经在处理动画时达到了其极限,这一更新就变得尤为必要。

isfiberreadyyet.com等网站说明了当时React开发的心情。图1.1显示了该网站在2017年3月26日的样子。

图1.1isfiberreadyyet.com/2017年3月26日

这个网站使用一个醒目的“No”回答了新版本是否已经发布的问题。你还可以查看库单元测试的状态。

终于,在2017年9月26日,React 16作为全新的稳定版本公开发布。

随着新的reconciliation算法的推出(我们将在本章中更详细地描述其功能),以及随后发布的多个小版本,React的核心部分也进行了许多改进和增强:

React 16.2

在React16.2版本之前,组件的生命周期方法设计并没有考虑到组件树的创建可能会因为某些原因而被中断。新的生命周期方法的引入是为了支持这种可能的中断情况。例如,这就可能会中断组件树的创建。在处理动画时可能会有更高优先级的DOM更改需要插入。另外,React 16.2版本还对Context API进行了彻底的完善。Context API允许在组件树的不同层级之间共享信息,之前的接口经过调整可以更加方便地使用。

React 16.4

React16.4的一个重要特性是平台独立性。从16.4版本开始,React可以在不同类型的设备上使用,无论是移动设备还是桌面系统都支持。为了实现这一点,React 16.4版本新增了对指针事件的支持。这意味着React现在可以原生处理触摸屏和手写笔等输入设备,极大地增强了在各种设备上的兼容性和用户体验。

React 16.6

在React开发中,性能一直是一个重要话题。React 16.6引入了懒加载(lazy)功能,通过使用像lazy函数这样的功能,React实现了Suspense(暂停渲染)特性的初步功能。使用懒加载,组件可以异步加载,并在此期间显示一个占位符。此外,组件的静态contextType属性使得访问Context API更加便捷。

React 16.8

在这个版本中,引入了钩子(Hooks)API。虽然这个特性乍一看似乎不显眼,然而,在这个特性的背后是React功能组件的重大升级。通过使用钩子,我们可以在函数组件组件中实现组件的生命周期和组件自身的局部状态,而在此之前,只有类组件才能使用局部状态。关于钩子的更多信息,请参阅第6章。钩子使得组件的逻辑和状态管理与UI渲染之间的关系进一步解耦。

钩子不但增强了了React功能,同时钩子API的引入并没有带来任何破坏性变化,因此这一扩展也成为了小版本更新的一部分,符合了React成为更高效和易用的库的路线图。

React 16.x版本

另一项旨在提高应用性能的特性是并发模式,也称为异步模式。这个特性允许在一个独立的进程中计算应用程序的组件层级,而不会阻塞主浏览器进程。lazy函数实现了suspense特性的第一部分,使得可以异步加载组件。Suspense for Data Fetching(数据获取暂停渲染机制)特性确保了其他服务器请求(例如异步的fetch调用以读取数据)能够灵活处理。

React17:无新功能更新

语义版本控制的方法规定主版本号的更新可能会带来破坏性的功能更新。React 17版本的发布对社区来说尤其令人惊讶。因为这一版本的公告标题是“无新功能”,此版本的重点是简化现有应用程序升级到新版本的过程。开发团队在这个版本中引入了渐进式升级功能,允许开发者将应用程序逐步升级到新版本。

React 17的另一项在变化是在事件处理方面。React不再在文档级别(即整个网页)上注册事件监听器,而是将事件监听器注册在应用程序的根节点上。这一变化旨在优化事件处理的性能和管理。

随着服务器组件的引入,React开始将客户端功能和服务器端功能更紧密地结合在一起。这一功能旨在将React组件在浏览器中的交互性操作与服务器端的性能相结合。和大多数重大新功能一样,服务器组件最初被作为实验性功能添加到库中。

React 18:并发模式React

React18的最重要特性是并发渲染器。这一特性允许React可以在后台同时处理和准备多个界面状态。并发渲染器改变了之前的渲染过程原则,使得库能够中断渲染过程、稍后继续渲染,或者启动新的渲染过程。对于应用程序用户来说,这意味着界面响应更快,因为应用程序可以更及时地响应用户的交互操作。

除了并发渲染器之外,React 18还为外部框架(如Next.js)引入了数据获取的Suspense特性的支持。

从React的发展历程中,可以明显看出,React的重点不仅在于提升性能,还致力于提供良好的用户界面可用性。React的进步不仅由Facebook推动,Facebook战略性地利用React来构建Web前端,还受到一个大型且活跃的社区的支持和推动。