React、Umi、RN 整体理解

发布时间 2023-11-17 19:16:06作者: 背包の技术

可以少去理解一些不必要的概念,而多去思考为什么会有这样的东西,它解决了什么问题,或者它的运行机制是什么?

React

1. React 起源和发展(是什么?)

React 是用于构建用户界面的 JavaScript 库,起源于 Facebook 的内部项目,该公司对市场上所有 JavaScript MVC 框架都不满意,决定自行开发一套,用于架设 Instagram 的网站。于2013年5月开源。

React 与传统 MVC 的关系:

React 并不是一个完整的框架,最多认为是 MVC 中的 V (View),即 React 一般被用来作为 MVC 中的 V 层。做为 V 层构建用户 UI 的库,可以简单的理解为,React 将页面分成了各个独立的小块,每一个小快就是一个组件,这些组件之间可以组合、嵌套,就成了我们的页面。

它不依赖其他任何的库,在开发中,可以与任何其他的库集成使用,包括 Jquery。React 的思想非常独特,性能出众,可以写出重复代码少,逻辑清晰的前端代码。它可以在浏览器端运行,也可以通过 nodejs 在服务端渲染。

2. React 的特性

  1. 声明式设计:React 采用声明范式,可以轻松描述应用。

    React 使创建交互式 UI 变得轻而易举。为你应用的每一个状态设计简洁的视图,当数据变动时 React 能高效更新并渲染合适的组件。以声明式编写 UI,可以让你的代码更加可靠,且方便调试。

  2. 高效(虚拟 DOM):React 通过对 DOM 的模拟使用了虚拟 DOM,可以最大限度地减少与真实 DOM 的交互。

  3. 灵活:React 不依赖其他任何的库,在开发中 React 可以与已知的库或框架很好地配合。

  4. 组件化:通过 React 构建组件,使得代码更加容易得到复用(复用复用复用),能够很好的应用在大项目的开发中。

    构建管理自身状态的封装组件,然后对其组合以构成复杂的 UI。由于组件逻辑使用 JavaScript 编写而非模板,因此你可以轻松地在应用中传递数据,并保持状态与 DOM 分离。

  5. 单向响应的数据流:React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

    单向数据流,数据流方向是由从上到下(父到子)的,如果下面子组件数据发生改变(更新)了,要从子组件发送到父组件,父组件更新完了之后再次传递给子组件(也就是说子组件数据更新后,需要父组件重新的给它流入一遍),这个时候父子组件都可以使用这个数据。

    比如说:老板下达任务给下属,然后下属执行。 如果此时下属有个想法(比如修改个某某数据),这时需要请示领导,如果领导同意了,那么下属得到新的命令再去执行。好处就是,所有的主动权都在顶层组件,下面所有的变动上面都知道。如果什么事低下自己决定,直接修改完,告诉上面。出问题调查起来麻烦,不知道上面还是下面出了问题。

  6. JSX: JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。

    React 的语法是 JSX,通过使用这种语法,可以在 React 代码中直接混合使用 js 和 html、css 来编写组件代码,这样代码的逻辑就非常清晰,当然也意味着,需要将 jsx 代码编译成普通的 javascript 代码,才能在浏览器中运行, 这个过程让 React 中的处理器去解析 JSX 就行了。

  7. 一次学习,跨平台编写:

    无论你现在使用什么技术栈,在无需重写现有代码的前提下,通过引入 React 来开发新功能。React 还可以使用 Node 进行服务器渲染,或使用 React Native 开发原生移动应用。

3. React 的缺点

并不是一个单独完整的框架,React 是目标是 UI 组件,通常可以和其它框架组合使用,目前并不适合单独做一个完整的框架。

4. 什么是虚拟 DOM?

4.1)传统 DOM 更新

真实页面对应一个 DOM 树,在传统的开发中,每次需要修改、更新页面时,都需要手动直接操作 DOM 来进行更新。

4.2)虚拟 DOM

DOM 操作非常昂贵。我们都知道在前端开发中,性能消耗最大的就是 DOM 操作,而且这部分代码会让整体项目的代码变得难以维护。React 把真实的 DOM 树、数据转换成 JavaScript 对象,也就是 Virtual DOM(虚拟 DOM、VDOM、vnode)。也就是说在 React 中用 JS 对象来描述虚拟 DOM 树。

比如在 React 中,render 执行的结果得到的并不是真正的 DOM 节点,而是 Virtual DOM, 即仅仅是轻量级的 JavaScript 对象 。

虚拟 DOM 原理:

React 会基于真实 DOM 和数据创建两条虚拟 DOM ,用 DIFF 算法以最小的代价对比(DIFF)出两个虚拟 DOM 数据节点是不是有改变。从而只选择将需要修改的部分给标记起来,做一个补丁,真正更新到真实的 DOM 中。

不动其他 DOM 只会影响改变的 DOM,其他 DOM 节点不需要重新创建的,只需要调整位置。

React 虚拟 DOM 核心思想:

对复杂的文档 DOM 结构,提供一种方便的工具,进行最小化地 DOM 操作。这句话,也许过于抽象,却基本概况了虚拟 DOM 的设计思想。

虚拟 DOM 总结:

虚拟 DOM 是 React 的一大亮点,具有 batching(批处理)和高效的 Diff 算法。这让我们可以无需担心性能问题而“毫无顾忌”的随时“刷新”整个页面,由虚拟 DOM 来确保只对界面上真正变化的部分进行实际的 DOM 操作。在实际开发中基本无需关心虚拟 DOM 是如何运作的,但是理解其运行机制不仅有助于更好的理解 React 组件的生命周期,而且对于进一步优化 React 程序也会有很大帮助。

虚拟 DOM 实例:

React 会基于真实 DOM 和数据创建两条虚拟 DOM,这里就可以做一个对比:前后两条没有做出改变,中间少了一条,这时候给他标记起来,做一个补丁 patch(s) ,真正更新到真实的 DOM 中。

// 原始基础数据:[111, 222, 333],基于基础数据创建出来的虚拟 DOM 如下:
{
	{
    type:"li",
    text:"111",
  },
  {
    type:"li",
    text:"222",
  },
  {
    type:"li",
    text:"333",
  },
}

// 修改后的数据:[111, 333],基于新的基础数据创建出来的虚拟 DOM 如下:
{
	{
    type:"li",
    text:"111",
  },
  {
    type:"li",
    text:"333",
  },
}

4.3)DOM 直接操作对性能的影响

DOM 直接操作将导致回流重排严重影响性能,比如减少的 Dom 删掉,下面的 Dom 需要往上移,引发文档的重排,回流的问题。频繁改变 DOM 就会导致回流现象,回流就是重新排列下它的顺序,然后重新渲染一遍,就会影响我们的性能。

Umi

Umi,中文可发音为乌米,是可扩展的企业级前端应用框架。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。其次 Umi 本身是基于 React 构建的。

create-react-app 是基于 webpack 的打包层方案,包含 build、dev、lint 等,他在打包层把体验做到了极致,但是不包含路由,不是框架,也不支持配置。所以,如果大家想基于他修改部分配置,或者希望在打包层之外也做技术收敛时,就会遇到困难。

React Native

React 是用于构建用户界面的 JavaScript 库,是基于浏览器的。React Native 可以基于目前大热的开源 JavaScript 库 React.js 来开发 iOS 和 Android 原生 App。

React 和 React Native 的区别:

1)框架作用的平台不同

RN 是由 React 衍生出来的,两种框架都是用 JSX 开发语法,但是 RN 是用来开发真正基于原生渲染的 iOS 和 Andriod 移动应用的 JS 框架,而React 是将浏览器作为渲染平台。

2)工作原理的差别

Virtual DOM 是介于开发者描述的视图与实际在页面上渲染的视图之间。在浏览器上如果想渲染出来可交互的用户界面,开发者必须操作浏览器的文档对象(document object model),Virtual DOM 的出现,就是为了节省这部分操作所消耗的性能。但是 Virtual DOM 的巨大潜力,是在于这个抽象层,可以带来很多可能性。

React Native 的工作原理,就是调用 Objective-C 的 API 去渲染 iOS 组件,调用 Java API 去渲染 Android 组件,而不是渲染到 DOM 上。桥接使得 React 可调用宿主平台开放的 UI 组件,React 组件通过 render 方法返回了描述界面的标记代码。如果是 Web 平台,React 最终把标记代码解析成浏览器的 DOM;而在 React Native 中,标记代码会解析成特定平台的组件,例如会表现成 iOS 平台上的 UIView。

3)渲染周期

React 的渲染周期开始于 React 组件挂载到 DOM 之后,接着 React 进入渲染周期并根据需要渲染组件。在渲染阶段,React 将开发者在 return 中返回的 HTML 标记直接按需渲染到页面上。

React Native 生命周期与 React 基本相同,在渲染上因为 React Native 依赖于桥接,并不在 UI 主线程运行,它可以在不影响用户体验的前提下执行这些异步调用。

4)创建组件

当编写 Web 环境的 React 的时候,视图最终需要渲染成普通的 HTML 元素;而在 React Native 中,所有元素都会被平台指定的组件替换,例如在 iOS 中,组件被渲染成 UIView,而在 Android 平台,会被渲染成 View。UI 元素均为 React 的(原生的)组件,而不是基础的 html 元素,因此在使用每一个组件的时候,都需要显式的导入。

5)原生的样式

在 Web 中,使用 CSS 样式为 React 组件添加样式已经是开发过程中不可获取的一部分了。React 通常不影响我们编写 CSS 的方式,并且它确实让样式的动态创建更加容易(通过 state 和 props),除此之外,React 基本上不关心我们如何处理样式的。

非 Web 平台上有大量的方法来处理布局和样式,我们使用 React Native 时,只需要用一种标准的方法来处理样式,React 和宿主平台之间的桥接包含了一个缩减版 CSS 子集的实现,这个 CSS 子集主要通过 flexbox 进行布局,做到了尽量简化,而不是去实现所有的 CSS 规则。有别于 Web 平台,CSS 的支持程度因浏览器而不同,React Native 则做到了样式规则的一致。

6)宿主平台 Api

使用 Web 环境的 React 与 React Native 最大的不同,在于宿主平台的 Api。

在 Web 中,我们通常要处理采纳标准的不一致和碎片化所引起的问题,并且大多数浏览器只支持部分核心的特性。然而在 React Native 中,平台特定的 Api 在提供优秀原生的用户体验方面发挥了巨大的作用。当然,要考虑的方面还有很多。Api 囊括了许多功能,从数据存储到地理服务,以及操控硬件设备(如摄像头)等。非常规平台上的 Api 会更有趣,例如,React Native 和虚拟现实头盔之间的 API 会是什么样的呢?

默认情况下,iOS 和 Android 版本的 React Native 支持许多常用的特性,甚至可以支持任何异步的本地 Api。React Native 让宿主平台 Api 的使用变得更加简单和直观,你可以在其中自由地试验。同时,务必思考一下怎样做才符合目标平台的体验,并在心里设计好交互过程。毋庸置疑,React Native 的桥接不可能暴露宿主平台全部的 Api。

如果你需要使用一个未支持的特性,完全可以自己动手添加到 React Native 中。另外,如果其他人已经集成,那就更好了,所以应该及时查看社区中的实现。值得注意的是,使用平台 Api 也会对代码复用有帮助。同时,实现平台特定功能的 React 组件也是平台特定的。

隔离和封装这些组件将会给你的应用带来更大的灵活性。当然,这对你开发 Web 应用同样奏效,如果你想共享 React 和 React Native 的代码,请记住像 DOM 这样的 API 在 React Native 中并不存在。