为什么我从 Angular 转向 React
Posted 全栈开发者中心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么我从 Angular 转向 React相关的知识,希望对你有一定的参考价值。
在过去的一段日子里我大量地使用了 Angular 1.x,直到我开始使用 React。这两个项目我使用得比较广泛。但是,其中有几个原因使我转向了 React。刚开始原因还不是那么清晰,但现在回顾起来,我认为我可以对此作出一个很好的总结了。
为什么我从 Angular 迁移到 React?我给出了 10 个理由。过去我喜欢 Angular 的各个方面,但是该是时候移除它了。这篇文章帮助人们理解 React 的优点, 也会让人们了解 Angular 的优点,之后,再让人们在 Angular 或 React 间作出选择,或甚至是在 React 与 Angular 2 间作出选择。
本文并不打算批判 Angular。 长期以来,对我来说 Angular 具有很优秀的单页应用程序体验。 我喜欢这个框架,因为它给你所需要的一切。 由于我只是广泛使用过 Angular 1.x,所以本文不打算谈论 Angular 2,但我认为大多数的框架背后的原理仍然是相同的,本文所述同样适用于 Angular 2。最后,在此我仅关于这两种解决方案提供我的个人经验。
文章不是对两种解决方案进行比较,而是关于为什么考虑使用 React 作为解决方案的反思。 比较苹果和橘子是毫无意义的。 但是,反思你为什么可以使用或你为什么选择了一个特定的工具却是有意义的。
接下来让我们来看看我现在喜欢使用 React 的 10 个原因。
React 仅是一个视图库
单页应用程序(SPA)遵循基于组件的用户界面的常识。组件获取输入并返回组件的实例作为输出。例如,输出可以是简单的按钮元素。你只需要为你的组件定义一次输入输出和内部行为,然后就能在任何 DOM 层次中随意地使用它来创建实例了。在最佳情况下,定义的组件易于重用并容易组装到其他组件中。
React 是基于组件的用户界面的理想选择。它只是一个视图库,并解决了所有已描述的组件的要求。它是一个致力于仅解决一个问题的库:提供了所有用于构建一个基于组件的用户界面的工具。
你可以看到 React 是作为 SPA 的一个组成部分。一旦你需要解决其他问题,你需要其他构建块。您的应用程序需要路由?可以看看适合 React 的路由解决方案。您的应用程序需要可扩展状态管理?可以看看不同状态管理器的解决方案。您需要执行异步请求吗?可以看看像 fetch, axios 或 superagent 的解决方案。
不过只用 React 也可以构建应用程序。它可能没有应用程序所需的成熟的路由和复杂的状态管理,但是它用于小应用程序没有问题。在 React 学习之路通过构建这样的应用程序来介绍了 React。
React 本身只是应用程序的一个构建块,它提供了基于组件的用户界面解决方案。像其它的构建块一样,它是可替换的。基于用户界面,你可以使用另一个解决方案来构建组件,它仍然可以和与其它构建块结合。
从这一点来看 Angular 是不同的。它不是一个库,而是一个框架。它提供了不止一个构建块。它是更刚性的解决方案。ReactJs 生态系统及其所有构建块放在一起也可以看作是一个框架。但是与 AngularJs 相比,React 的构建块是可替换的。而 Angular 帮你做好每件事。这看起来有些矛盾,一方面它应该很容易学,因为是使用自己的构建块,但另一方面,同时学习每一个构建块却相当困难。在 React 中想一次学很多东西也不容易。
React 是一个创新的地方
React 只是生态系统的核心,它周围所有的东西都是由构建块组成。你可以灵活地选择构建块去解决不同的问题。但是 React 依然保持着他们之间简单交换风格。他们之间简单的交换风格,让各种新奇的方法得以萌生。你可以使用 Redux 和 MobX 作为状态管理的示例。Redux 在早期就已经拥有了很强劲的势头,那时,MobX 还是一个小小社区的倡导者,他可以让那两种解决方案相互交换。
即使交互是 React 的核心建筑块。最近,像 Inferno 和 Preact 这样的库也开始和 React 竞争,他们可以用来代替 React。在 Augular 中使用这些方法是没有任何意义的,因为 Augular 有它自己的解决方式。
在 React 中可交换构建块,这使得尝试新方法成为可能。它的每个方法都给社区留了适应的空间,这使得 React 生态系统不断创新。
JSX - 混合了 HTML 和 JavaScript
React 有一套称为 JSX 的语法,用来制作组件。JSX 混合了 html 和 javascript。此外人们经常会在元素中使用内联样式,即混入 CSS。一开始可能让人觉得混淆,但终归会适应。你可以使用 JavaScript 组合和操作 DOM,但是它嵌入在 HTML 中。你可以使用内置的 JavaScript 功能,比如 map 和 filter 来显示多个(过滤后的)DOM 节点。你还可以使用三元操作来按条件进行渲染。你可以在 HTML 中使用完整的 JavaScript 功能。
在 SPA 解决方案中,它是一个新奇的方法,通过混合 HTML 和 JavaScript 来定义组件。其实这种方法在很早的服务端渲染方案(比如 JSP)中就已经存在了。
与之相反,Angular 清楚地区分了逻辑和视图的概念。它可以在 HTML 中使用内置的表达式,像 ng-repeat(Angular 1.x)或 ngFor(Angular 2)。这在 JSX 中会使用原生 JavaScript 的 map() 来完成。
React 的 API 很简单
React 是一个视图库。它只解决一个问题并把这个问题处理好。因此需要学习和理解的方法会很少。
React 组件使用生命周期方法。在 React 的 ES6 类组件中,你可以使用生命周期方法进入到组件生命周期。通常只需要写 render() 这个生命周期方法,它把元素作为组件的新实例来进行渲染。渲染的代码块会在组件初始化和每次组件更新时运行。这就够了。不过你可以使用多个生命周期方法来添加高级的组件行为。比如,你可以使用 constructor() 来初始化有状态的组件并添加类方法来操作状态。每次状态发生改变生命周期方法都会再次运行以更新视图。
组件的生命周期方法一共只有 9 个。多数情况下,你只会用到其中一半 - 哪怕是在成熟的 React 应用程序中。
然后你还需要知道两个 React ES6 类组件的方法:setState() 和 forceUpdate()。你一般不会用到后一个方法,它用于通过编程来强制更新一个组件。不过 setState() 通常用于更新组件的内部状态,这些状态是在 constructor() 生命期函数中初始化的。想像一下,你的列表组件中有一系列的项。然后你想从列表中添加或删除元素。你可以使用把列表保存在组件的内部状态 this.state 中,再通过 setState() 更新列表。
在 React 的官方文档 中你可以深入产了解 React 组件 API。
现在你已经知道了所有基本的组件方法。React 中还有其它一些概念,比如 props 和 state、children 属性或不同的组件申明。你可以慢慢来,一步一步地学完它们。
总之 React 本身没有陡峭的学习曲线。它只是一个需要掌握少量方法的视图层。如果你首先学习的 React,我建议只学习 React,不要再学其它的。《React 学习之路》就是这种学习思想,它涵盖了所有上面提到的你需要学习并掌握 React 的主题。
轻量级组件 => 最佳实践
React 中的组件有两个定义方式:ES6 类组件和函数形式的无状态组件。后者只是一些函数,接收参数输入并返回输出一个元素——这也是组件,但是它们不需要模板,只需要定义普通的 JavaScript 函数。我不能说 Angular 定义组件更容易。
function Button({ onClick, children }) {
return (
<button onClick={onClick} type="button">
{children}
</button>
);
}
随处使用函数式的无状态组件是个非常好的实践,但只在不需要组件状态和生命周期方法的时候才能这样做。这个最佳实践使你可以定义轻量级的小组件,却不失重用性、组件化和功能性,并且不会带来副作用。这样的最佳实践已经体现在上面的样板代码中。
单向数据流
与 Angular 1.x 不同,React 没有双向数据绑定。Angular 组件中的状态管理最终变得混乱不堪。状态几乎不能预测,也没有比较好的做法来处理它。在 Angular 1.x 中消除循环更新是件困难的事情。
React 使用单向数据流规则。组件使用 setState() 来显式更新内部状态。它必须从组件的状态对象 (this.state) 中获取状态,然后组件按更新后的状态再次渲染。对于组件的输入 (props),也会发生同样的事情,如果输入更新了,组件会通过其生命期方法 render 来更新。千万不要直接修改输入 (props) 或组件内部状态 (state)。应该遵循单向数据流规则,使 React 的状态管理更容易预测。
此外,你还可以完全控制原生 HTML 元素。例如,HTML 中的 input 有其自己的状态。你在 input 中输入的文本可以通过 value 属性获得。在 React 中如果想完全控制 input 的状态,以便在 input 的值发生改变时能通过 onChange() 回调,调用 setState() 来更新组件内部状态的值。之后可以在 input 中使用更新后的状态值。这样一来,组件内部状态就是单一来源,值得信任。而 input 不再自己管理状态。
<input
value={this.state.value}
onChange={(event) => this.setState({ value: event.target.value })}
type="text"
/>
单向数据流使得 React 的状态管理可预测且易于维护。
Redux
Redux 并非 React 的必备组件。不过它们能完美适配,因为 Redux 只是一个构建块,而 React 生态接受构建场。
Redux 带来可预测的状态管理。自 2015 年 Dan Abramov 引入 Redux 以来,它就完全符合 flux 体系。Redux 是 flux 库中的佼佼者,广泛应用于各种场景。在 React 中使用 Redux 是很自然的事情。React 本身使用单向数据流,这与 Redux 相符。
再来说 Angular 开发的那些日子里,开发者们奋斗在包含状态管理的可伸缩的成熟应用中。在某些时候,你必须自己实现像 flux 那样的东西,因为 flux 还没成形。最后每个人都在羡慕 React 的开发者拥有无缝集成在生态系统中的 flux 模式。
Redux 本身就是一个完整的生态系统。它是一个有着创新的构建块,像 React 一样。特别是在异步领域,它支持不同的方式。比如,你可以选择 JavaScript Promise、generator 或者可观察对象。它是一块试验田,你可以在这里找到自己做事的方法和创意。
接近 JavaScript
我必须说,从 Angular 转向 React 的过程中我学习了不少 JavaScript 语言的概念。现在再回到 Angular,我很难回想起它的语法、用于 HTML 的表达式,或者申明。因为我没有保留代码片段,所以回去使用 Angular 会花不少时间。我不知道事实是怎么样的,但是从 Angular 转回 React 的时候,我认为那是不同的开发方式。React 非常接近 JavaScript,它只有一个构建块。你一旦学会,就不是那么容易忘记。
React 非常接近 JavaScript。不仅 React,它的生态系统也与 JavaScript 类似。比如,Redux 的 action 和 reducer 本身就是 JavaScript。另外,整个 Redux 生态系统完全使用原生存在或即将实现的 JavaScript 功能,比如 generator 和可观测对象。从库的角度来看,它涵盖的内容中没有不是原生 JavaScript 的工具函数。
另一个方面是 JavaScript ES6。也许 React 包含 ES6 只是一个巧合,因为 ES6 出现在同一时间。不过 React 一直在前进并吸收 ES6 的优点。采用 ES6 是件好事。还记得之前定义的无状态的功能性按钮组件吗?如果使用 ES6 的箭头函数,它看起来会有点不一样:
const Button = ({ onClick, children }) =>
<button onClick={onClick} type="button">
{children}
</button>
在 React 及其生态系统中,你可以使用 ES6 简洁优雅地进行表达,而且它还简单并极具可读性。使用它是自然而然的事情。
函数式编程
函数式编程自然地溶入了 React 及其生态系统。也许这是因为它与 JavaScript 极为接近。作为一个 React 开发者,应该尽量定义没有副作用的函数 —— 纯函数。这些函数能以可预测的方式组进行组合。首先,因为它们是纯函数,相同的输入一定会得到相同的输出(可预测)。其次,你可以使用高阶函数来组合它们(可组合)。
可预见性和可组合性带来的优势同样赋予了 React 的功能性组件,这就是为什么 React 的组件是可预测和可组件(高阶)的。
编程方式正在发生变化。函数式编程并不是新事物,但它是首次在 JavaScript 中采用。对于 JavaScript 生态环境中的函数式编程来说,React 是这个思想的引领者之一。人的伟大之处就在于能向伟人学习,了解他们的优点和缺点并借他们的手来提高自己。React 和它的生态系统为你学习和使用函数式编程提供了可能性。
社区
如果说下述大部分原因不适用于其它库、框架和生态系统,那我是在撒谎。但我仍然认为值得提一下,React 环境背后的社区非常伟大。
生态系统背后的人每天都在反复不断的尝试。这可以追溯到 React 发明出来的时候,这关系到它的构建块。新的解决方案有机会在社区中茁壮成长。构建块会从开发者那获益并不断变化。
React 背后的人们相互鼓励。人们向社区贡献创新、扩展库或写文章,怎么都行。大家都会点赞激励你继续。当我开始写关于 React 的文章时也受到了大家的鼓励。
人们不会在生态系统中驻足。如果出现问题,就一定会有解决办法。有人会用库来解决问题,或者在文章中解释某个问题的最佳实践。人们协助奋进。因为社区持续创新,所以总会有不少解决问题的新颖方案。
正如我所说,我关于社区的想法是普遍的想法。我认为充斥着不同解决方案的社区都做的很好,它们相互鼓励共同进步。这样的环境下它怎么会不变得伟大。
总之,我说的这些是希望能帮助你更好的了解 React 生态系统。这也许会帮助你决定是否要在 2017 年跳上 React 这趟列车。对我个人来说,它帮助我进行了反思以决定开始学习 React。去年年中我们公司也在这个方面有一些小小的进步。
原文:https://www.robinwieruch.de/reasons-why-i-moved-from-angular-to-react/
译文:https://www.oschina.net/translate/reasons-why-i-moved-from-angular-to-react
以上是关于为什么我从 Angular 转向 React的主要内容,如果未能解决你的问题,请参考以下文章