原文:How to Sprinkle ReactJS into an Existing Web Application
译者:nzbin
当我们学习一项新技术,可能是一个 JavaScript 框架,也可能是一个 CSS 方法,我们将面对这样的挑战 如何在旧网站上运用这项新技术?
。很多教程讲述了如何从头开始,但却很难运用到实际工作中。
在这篇教程中,我会通过一些很基本的例子讲解如何灵活运用 ReactJS,以及替换使用 jQuery 写的代码。
从 jQuery 到 React
我最近的任务是用 React 重构一个使用 jQuery 写的功能。这个过程困难重重,因为大量的 jQuery 分散在代码段中。使用 jQuery 构建所有的 UI 是可能的(我们已经这样做了很多年),但是在规模变大之后,将变得混乱且难以维护。
无论你使用 Angular, Ember, Vue, React, 或者只是 jQuery,你所做的事情和开发者多年来所做的事情是一样的:
渲染 HTML > 接收用户事件 > 重新渲染 HTML
因为 jQuery 非常依赖选择器比如 .classes
和 #IDs
去控制 DOM,所以大量的属性会使 HTML 变得容易混淆,而这些属性的目的只是方便 jQuery 查找。如果代码量比较小,这是没有问题的, 但是如果代码量庞大,就会很难知道哪些类用于 CSS,哪些类用于 JavaScript。如果你之前为了改变一个功能而在 HTML 模板或 JavaScript 中查找 find
一个 .class
或者 #ID
选择器,你应该明白我说的。
过渡依赖
.classes
和#IDs
的选择来操纵 HTML 并不轻松。
所以,如果你的代码是用 jQuery 或者其它框架所写,那么应该如何使用 React 去替换这些 UI 片段?
开始之前应该了解的事情
Wrapper / Container 元素
无论使用 jQuery 还是下一个流行框架开发应用,大多数情况都是用一个根元素包裹 UI 片段。如果代码库使用 jQuery,通常会有一个元素充当 wrapper 选择器。使用 jQuery 选择 wrapper 元素,它被用于动态更新 DOM。
<!--
.MyAwesomeFeature acts as a container to select
and manipulate child components with jQuery.
-->
<div class="MyAwesomeFeature">
<div class="MyAwesomeFeature__title"></div>
<div class="MyAwesomeFeature__image"></div>
</div> <script>
var container = $(".MyAwesomeFeature");
$(".MyAwesomeFeature__title", container).text("Hello World!"); // Other DOM changes, event handlers, etc...
</script>
独立状态 vs. 共享状态
可以看一下你的应用中的功能状态是独立 isolated
于 container 元素还是在多个元素*享 shared
。
独立状态 - 这种状态独立存在于 container 元素中。所有按钮、输入框等的交互状态都由这个 wrapper / container 元素分享。
- 共享状态 - 这种状态由多个元素共享。比如,从页面其它位置的日期下拉框中更新日历。 菜单和日历在不同的容器中,但是它们的状态是共享的。
我将用 jQuery 和 ReactJS 做的 4 个例子解释共享/独立状态的概念。
用 jQuery 实现独立状态
假设我们有一个 web 应用,它展示了一个 emoji,当点击按钮,会随机展示一个新的 emoji。下面的代码是一个典型的 jQuery 应用,我们选择父级元素 .mood-container
,然后动态改变内容。
以下是例子 的 HTML:
<!--
Demonstrates how jQuery can be used to
use a container as a selector and update
the content within.
-->
<div id="mood-container">
<div class="Mood">
<div class="Mood__emoji"></div>
<div class="Mood__name">[ Emoji Placeholder ]</div>
<button class="Mood__button">Random Mood</button>
</div>
</div>
See the Pen Isolated state with jQuery by Andrew Del Prete (@andrewdelprete) on CodePen.
这并不是使用 jQuery 更改 DOM 的唯一策略,但很常见。
用 ReactJS 实现独立状态
使用如 React 的库的好处之一就是可以将上面的 JavaScript 和 HTML 封装成一个组件 component
。它是一个更可靠、可维护、可重用的功能部件。
这在处理大型应用时非常有用,因为组件 component
的渲染和更新是同步的。我并不是指将关注点与逻辑和视图层混合在一起,而是如何将 JavaScript 和 HTML 以组件 component
的形式组织代码。这是所有 JavaScript 框架的共同理念,因此被称为 Framework
。
所有框架通常都是:
- 挂载到特殊的容器 container上 ( 比如
App
中名为#ID
的 div)。
- 向容器 container 中渲染内容。
- 负责跟踪和更新容器 container 中的内容。
- 负责移除容器 container 中的内容。
以下是使用 React 整合后的新的 HTML:
<!--
Demonstrates how ReactJS mounts itself
to a container and takes it from there.
-->
<div id="mood-container" />
See the Pen Isolated state with ReactJS by Andrew Del Prete (@andrewdelprete) on CodePen.
用 jQuery 实现共享状态
使用 jQuery 可以很容易实现,但是,如果一个区域动态影响另一个单独使用选择器的区域时,可能会变得混乱。另外,当你使用 .classes
以及 #IDs
作为选择器手动控制 DOM 的时候,你要负责跟踪所有事情的开销。
See the Pen Shared state with jQuery by Andrew Del Prete (@andrewdelprete) on CodePen.
在这个例子中,我们通过 .Mood__name
和 .Mood__button-name
选择器分享 mood name ,并且通过一个容器中的按钮去更新另一个容器中的 emoji 。这还可以写的更简单一些,但是不管怎样,当尝试用 jQuery 选择器单独管理所有这些事情时,就会变得很糟糕。
用 ReactJS 实现共享状态
在 ReactJS 中,通常有两个分享组件状态的方法:
- 将组件包裹在 container 元素中去管理状态,将数据/函数作为 props 向组件传递。
- 使用类似 Redux 的工具在全局定义状态和 actions,然后将组件挂载上去。
使用 Container 分享状态
这是使用 React 渲染比较常见的方式,尤其 SPA 应用或者 UI 片段。因为我们希望组件之间通信,所以我们将它们放置在父级组件中,然后向下传递属性来更新每个子组件。这是 ReactJS 最基本的工作方式。
这种方式适用于多个 UI 组件被一个父组件包裹的情况。很多之前创建的应用可能不适合,但是可以根据 UI 布局情况选择使用。
See the Pen Shared state with ReactJS - Container by Andrew Del Prete (@andrewdelprete) on CodePen.
使用 Redux 分享状态
类似 Redux(flux 的另一种实现)的库可以很容易的实现应用中不同组件之间的通信。可以将 actions 和状态属性挂载到组件,通过更新全局对象 Redux 来分享状态。
See the Pen Shared state with ReactJS - Redux by Andrew Del Prete (@andrewdelprete) on CodePen.
总结
我希望这篇文章可以让你更好地了解需要关注的内容以及如何将 ReactJS 运用到现有的应用中。主要的解决方法就是,如果你使用 jQuery 处理 UI 片段,那么你可以将容器元素替换成一个 React 组件。如果你需要在多个组件中分享状态,那么你可以使用容器方法或者类似 Redux 的库。
感谢阅读!
-Andrew Del Prete