作者|David Kopal

译者|无明

出处丨前端之巅

使用 React 开发用户界面是一件很酷的事情,但我们能让它变得更酷、更好吗?要让它变得更好,我们首先需要找出它存在的问题。那么,React 作为 JavaScript 库还存在哪些问题?

React 最初并不是为 JavaScript 而开发

如果你仔细看一下 React,你会发现,它的一些主要原则与 JavaScript 有点格格不入。让我们来谈谈不变性、函数式编程原则,特别是类型系统。

不可变性是 React 的核心原则之一。你不想改变 prop 或 state,因为如果这样做了,可能会遇到不可预测的后果。但 JavaScript 并没有提供开箱即用的不可变性。我们通过约定的方式来保持数据结构的不可变性,或者我们使用 immutableJS 之类的库来实现不可变性。

React 采用了函数式编程的原则,因为 React 应用程序实际上是函数的组合。尽管 JavaScript 提供了一些这方面的特性(如一等函数),但它仍然不是一门函数式编程语言。当我们想编写声明性代码时,需要使用外部库,如 Lodash/fp 或 Ramda。

那么,类型系统有什么问题呢?在 React 中,我们有 PropTypes。我们用它们来模仿 JavaScript 的类型,因为它本身不是静态类型语言。为了利用高级静态类型,我们需要使用外部依赖库,例如 Flow 和 TypeScript。

React 和 JavaScript 的比较

如你所见,JavaScript 与 React 的核心原则不兼容。

有没有另一门编程语言与 React 具有更好的兼容性?

或许 ReasonML 就是这样的一门语言。

Reason 提供了开箱即用的不可变性。因为它是基于函数式编程语言 OCaml,所以也具备了 OCaml 内置的一些特性。Reason 还提供了一个强大的类型系统。

React、JavaScript 和 Reason 比较

Reason 与 React 的核心原则兼容。

Reason

Reason 并不是一门新语言,它是 OCaml 的另一种 JavaScript 风格的语法和工具链,而 OCaml 是一门已经存在了 20 多年的函数式编程语言。Reason 是由 Facebook 的开发人员创建的,他们已经在一些项目中使用了 OCaml(如 Flow、Infer)。

Reason 具有 C 语言风格的语法,这让来自 JavaScript 或 Java 等主流语言的人很容易上手。相比 OCaml,Reason 提供了更好的文档和不断增长的社区。此外,它还可以与现有的 JavaScript 代码库集成。

OCaml 是 Reason 背后的语言。Reason 与 OCaml 具有相同的语义——只是语法不同。这意味着你可以使用 Reason 的 JavaScript 风格的语法来编写 OCaml 代码。因此,你可以利用 OCaml 的强大特性,例如强大的类型系统和模式匹配。

我们来看一下 Reason 的语法示例。

let fizzbuzz = (i) => switch (i mod 3, i mod 5) { | (0, 0) => "FizzBuzz" | (0, _) => "Fizz" | (_, 0) => "Buzz" | _ => string_of_int(i) };for (i in 1 to 100) { Js.log(fizzbuzz(i))};

我们在这个例子中使用了模式匹配,但它仍然与 JavaScript 非常像,对吧?

不过,浏览器目前唯一可用的语言仍然是 JavaScript,所以我们需要将它编译成 JavaScript。

BuckleScript

BuckleScript 编译器是 Reason 的一个强大特性,它可以将 Reason 代码编译成可读且高性能的 JavaScript,并移除死代码。如果你所在团队中不是每个人都熟悉 Reason,就让他们阅读编译好的 JavaScript 代码。

Reason 与 JavaScript 非常相似,以至于编译器都不需要对某些 Reason 代码做任何修改。因此,你可以享受静态类型语言带来的好处,而无需修改任何代码。

let add = (a, b) => a + b;add(6, 9);

这段代码在 Reason 和 JavaScript 中都是有效的。

BuckleScript 附带了四个库:标准库 Belt(OCaml 的标准库不够强大),以及与 JavaScript、Node.js 和 DOM API 的绑定。

由于 BuckleScript 是基于 OCaml 编译器,所以编译速度比 Babel 要快得多,也比 TypeScript 快上几倍。

现在让我们编译我们在 Reason 中编写的 FizzBuzz 算法代码。

通过 BuckleScript 将 Reason 代码编译成 JavaScript 代码

如你所见,生成的 JavaScript 代码可读性很高,看起来就像是由 JavaScript 开发人员编写的。

Reason 不仅可以被编译为 JavaScript,还可以被编译为本地代码和字节码。因此,你可以使用 Reason 开发一个应用程序,然后在 macOS、Android 和 iOS 手机上的浏览器上运行。Jared Forsyth 开发了一款叫做 Gravitron(https://github.com/jaredly/gravitron)的游戏,它就是用Reason 开发的,它可以在我刚刚提到的所有平台上运行。

与 JavaScript 的互操作性

BuckleScript 还为我们提供了与 JavaScript 的互操作性。你不仅可以将 JavaScript 代码粘贴到 Reason 代码库中,还可以让 Reason 代码与 JavaScript 代码打交道。这意味着你可以轻松地将 Reason 代码集成到现有的 JavaScript 代码库中。此外,你可以在 Reason 代码中使用 NPM 生态系统中的所有 JavaScript 包。例如,你可以在一个项目中组合使用 Flow、TypeScript 和 Reason。

当然,事情并没有看上去的那么简单。要在 Reason 中使用 JavaScript 库或代码,首先需要通过 Reason 绑定将它们移植到 Reason。换句话说,需要对无类型的 JavaScript 代码赋予类型,然后才能能够利用 Reason 的强类型系统。

如果要在 Reason 中使用 JavaScript 库,可以通过浏览 Reason Package Index(Redex)数据库看看这个库是否已被移植到 Reason。Redex 是一个网站,它聚合了使用 Reason 和 JavaScript 库编写的库和工具。如果在那里找到了你需要的库,就可以将其作为依赖项安装,并在 Reason 应用程序中使用它。

如果没有找到你需要的库,就需要自己编写 Reason 绑定。如果你是个 Reason 新手,那么要注意,编写 Reason 绑定是一件很有挑战性的事情。

如果你只需要 JavaScript 库中的某些功能,就不需要为整个库编写 Reason 绑定,而是对需要使用的功能或组件编写绑定即可。

ReasonReact

这篇文章是关于如何使用 Reason 开发 React 代码,这要归功于 ReasonReact 库。

或许你还在想:“我仍然不知道为什么要使用 Reason 来开发 React”。

正如之前提到的那样,主要原因是 Reason 与 React 的兼容性比 JavaScript 更好。因为 React 是为 Reason 而生的,或者更准确地说是为 OCaml 而生的。

ReasonReact 之路

React 的第一个原型是由 Facebook 使用 Standard Meta Language(StandardML,OCaml 的表兄弟)开发的,然后被迁移到 OCaml,React 也随之被转录为 JavaScript。

这是因为整个 Web 都在使用 JavaScript,说出“我们将在 OCaml 中构建 UI”这样的话是不明智的。它确实奏效了——使用了 JavaScript 的 React 已被广泛采用。

然后,我们习惯了认为 React 就是 JavaScript 库。React 与其他库和语言一起(Elm、Redux、Recompose、Ramda 和 PureScript),让函数式编程在 JavaScript 中流行起来。随着 Flow 和 TypeScript 的兴起,静态类型也变得流行起来。因此,具有静态类型的函数式编程范式成为前端世界的主流。

2016 年,Bloomberg 开发并开源了 BuckleScript,这是一种将 OCaml 转换为 JavaScript 的编译器。他们因此能够使用 OCaml 的强类型系统来开发安全的前端代码。

函数式编程的普及以及 BuckleScript 的发布为 Facebook 提供了理想的环境,让他们萌生了回到最初使用 ML 语言开发 React 的想法。

他们采用 OCaml 的语义和 JavaScript 的语法创建了 Reason。他们还创建了 React 的 Reason 包装器——ReasonReact,提供了额外的特性,例如在有状态组件中封装 Redux 原则。这样一来,他们让 React 回归到了初心。

React 和 Reason 的威力

当 React 进入 JavaScript 世界时,因为 React 存在的不足,我们需要引入各种库和工具来。这也意味着项目对其他库的依赖性很高。有些依赖库还处在开发阶段,而且还会定期引入重大变更。因此,我们不得不在项目中谨慎维护这些依赖项。

这为 JavaScript 开发增加了另一层复杂性。

典型的 React 应用程序至少具有以下依赖项:

  • 静态类型——Flow/TypeScript
  • 不可变性——immutableJS
  • 路由——ReactRouter
  • 格式——Prettier
  • lint——ESLint
  • 辅助功能——Ramda/Lodash

现在让我们切换到 ReasonReact。

我们还需要这些依赖吗?

  • 静态类型——内置
  • 不可变性——内置
  • 路由——内置
  • 格式——内置
  • ling——内置
  • 辅助函数——内置

在 ReasonReact 应用程序中,你不需要这些依赖项,因为语言本身提供了很多关键特性。维护软件包将变得更加容易,并且不会随着时间的推移而增加复杂性。

这一切要归功于已有 20 多年历史的 OCaml。它是一门成熟的语言,所有核心原则都很稳定。

总 结

起初,Reason 的创建者面临两种选择。采用 JavaScript 在一定程度上会让它变得更好,但同时也会背上一些历史负担。

最终,他们走的是一条不一样的路。他们采用了 OCaml,一门成熟的语言,具有出色的性能,并对其进行了修改,让它看起来很像 JavaScript。

React 也遵循了 OCaml 的原则,这就是为什么在 Reason 中使用 React 会获得更好的开发者体验。React 和 Reason 是构建 React 组件的一种更安全的方式,因为有强类型系统的支持,你不需要处理大多数在 JavaScript 中存在的问题。

下一步

如果你是来自 JavaScript 世界,就可以轻松地上手 Reason,因为它的语法与 JavaScript 很像。如果你一直在使用 React,那么接下来会更轻松,之前所有的 React 知识都可以继续派上用场,因为 ReasonReact 具有与 React 相同的模型和非常相似的工作流程。这意味着你无需从头开始,在开发过程中边用边学 Reason。

在项目中开始使用 Reason 最好的做法是循序渐进地进行。你可以将 Reason 代码用在 JavaScript 中,反之亦然。对于 ReasonReact 也是一样的。你可以将 ReasonReact 组件用在 React JavaScript 应用程序中,反之亦然。这种增量方法已被 Facebook 开发人员所采用,他们在开发 Facebook Messenger 时就大量使用了 Reason。

相关链接

ReasonML:https://reasonml.github.io/

ReasonReact:https://reasonml.github.io/reason-react/

OCaml:https://ocaml.org/

BuckleScript:https://bucklescript.github.io/

Belt:https://bucklescript.github.io/bucklescript/api/Belt.html

为什么说ReasonReact是编写React的最佳方式?相关推荐

  1. 编写react组件_s! 这就是为什么ReasonReact是编写React的最佳方法的原因

    编写react组件 Are you using React to build user interfaces? Well, I am too. And now, you'll learn why yo ...

  2. 使用Typescript和React的最佳实践

    by Christopher Diggins 克里斯托弗·迪金斯(Christopher Diggins) 使用Typescript和React的最佳实践 (Best practices for us ...

  3. 编写react组件_React组件的“黄金法则”如何帮助您编写更好的代码

    编写react组件 以及钩子如何发挥作用 (And how hooks come into play) Recently I've adopted a new philosophy that chan ...

  4. 编写Dockerfiles的最佳做法

    编写Dockerfiles的最佳做法 Docker可以通过从Dockerfile包含所有命令的文本文件中读取 指令,自动构建图像,以便构建给定图像所需的顺序.Dockerfile坚持一个具体的格式,并 ...

  5. 编写react组件_如何编写第一个React.js组件

    编写react组件 React的函数和类组件,道具,状态和事件处理程序 (React's function and class components, props, state, and event ...

  6. 步进伺服控制程序 用三菱plc和威纶触摸屏编写 新手学习最佳选择

    步进伺服控制程序 用三菱plc和威纶触摸屏编写 新手学习最佳选择. 此程序已经实际设备上批量应用,程序成熟可靠,借鉴价值高,程序有注释. ID:8311650922480938工控数码编程

  7. 使用CodePen编写react代码

    开篇题外话: CodePen是一个在线编辑前端代码的网站,对于前端小白来说非常好用,除了可以同时编辑html.css.js之外,可以实时的看到编写网页的样子,真的很方便. CodePen网站链接:ht ...

  8. 学习 Python 的最佳方式

    Python 是世界上功能最多且最强大的编程语言之一.使用 Python,你可以编写自己的应用程序,创建游戏.设计算法.甚至编程一个机器人.学习 Python 还可以担任软件工程师.Web 开发人员. ...

  9. python游戏编程网课_Python 学习最佳方式_创建游戏_编程一个机器人

    Python 是世界上功能最多且最强大的编程语言之一.使用 Python,你可以编写自己的应用程序,创建游戏.设计算法.甚至编程一个机器人.学习 Python 还可以担任软件工程师.Web 开发人员. ...

最新文章

  1. FWFT FIFO读操作注意
  2. 如何搭建mysql的学习环境_Mysql学习笔记【一、环境安装配置】
  3. c语言程序设计A课程试,自学考试有关论文范文,与C语言程序设计A课程辅导相关硕士毕业论文范文...
  4. 为什么一定要回家?因为我们是中国人
  5. mysql 报错注入 读文件_SQL注入-读写文件
  6. PP团队圣经巨著《Application Architecture Guide2.0》14章-数据访问层
  7. 基于面向对象的图片轮播(js原生代码)
  8. android小米通知不显示电量,Android开发笔记——小米通知‘坑’ app的通知一直显示在不重要通知里 ......
  9. Alphabet旗下Sidewalk Labs试图通过比赛来打造智慧城市
  10. linux ssh最大会话数,Linux Shell 脚本限制ssh最大用户登录数
  11. pythonturtle是标准库_Python常用标准库1-Turtle,Random,Time和Datetime
  12. 中软国际软件测试培训中心,中软国际准员工培养计划C++开发/软件测试方向开班典礼...
  13. python:实现Lempel-Ziv压缩算法(附完整源码)
  14. cad渐开线齿轮轮廓绘制_CAD渐开线齿形怎么绘制
  15. Python+OpenCV人脸识别签到考勤系统
  16. MAYA简单操作讲解1--入门干货
  17. 结构体内数组arr[0]或者arr[1]变量的作用及使用方法
  18. 苹果新品“翻车”后,官方回应来了!
  19. 英文经典好歌《Nothing's Gonna Change My Love For You》没有什么能够改变我对你的爱-英译中
  20. oracle spfile 恢复,数据库恢复实例三:恢复spfile

热门文章

  1. 实战SSM_O2O商铺_30【商品】商品添加之Controller层的实现
  2. RocketMQ集群启动报错:java.lang.RuntimeException: Lock failed,MQ already started
  3. 普通平键的主要尺寸有_工字钢尺寸大全
  4. 对象存储使用案例_连云数据都有“对象存储”了,你还是单身?
  5. 阿里云云原生网关,开启下一代网关新进程
  6. python无法调用pygame,python-pycharm无法识别pygame程序包
  7. idea查看项目pid_idea启动时的端口号
  8. 深入理解ROS技术 【3】ROS下的模块详解(129-180)
  9. mysql 1个月多少天_在MySQL日期间隔中,1个月是否与30天相同? 1个季度与3个月相同吗?等等?...
  10. python爬虫抓收费图片_简单的Python抓taobao图片爬虫