[翻译]React抛开事物看本质

React JSX: The Other Side of the Coin

React发布的时候,很多人看到JSX都迷失方向(lost their minds)。javascript中的那些括号是干什么的?! 那么关注点分离理念呢? Facebook没有从社区中引荐什么吗?

至少可以这样说,和很多人一样,我对JSX最初的反应也是持怀疑态度的(skeptical)。但是当我渐渐喜欢上React的时候,每当我介绍给新开发者,我就感觉在秀自己的丑宝宝(作者真幽,还秀上了自
己爱子照片,这里省略掉)。

尽管有最初的想法,但后来我意识到JSX根本不是激进的(radical)想法。实际上,这就是事情的另一面。这是自然的演化转换过程。(It’s a natural evolutionary transition.) 为了理解为什么是这
样,请看后续故事。

阶段1: 非侵入式Javascript(Unobtrusive JavaScript)

非侵入式Javascript就是说HTML标签中不嵌入任何javascript代码。还记得jquery时代的那些日子吗? 非侵入式Javascript时代可谓百花齐放(in full bloom)。HTML是纯HTML,Javascript也是纯Javascript。关注点是完全分离的。

HTML代码可以这样写:

<a class=”hide”>Click to hide me</a>

Javascript代码可以这样写:

$('.hide').click(function() {-
  $(this).hide();
}-

完胜了,是不是? 其实不然。

似乎这是非常棒的思想。 HTML完全纯正!但是随后我们会发现一些问题: 我们怎么告知两者的互联关系呢? 答案是: 除非看完Javascript的每行代码,否则不能确定两者关系是啥。 这种模式中,要修>改HTML标签中的某行,就必须检查javascript中的每一行来确保这样修改没有破坏选择器。你瞧,这里实际上并没有做到完全的分离。确实,JS和HTML是在独立文件中了,但是这两个技术基本上是完全
联系在一起的(骨肉相连??join at the hip)。两者必须步调一致(lockstep),否则应用将会奔溃。

严格的HTML和JS的分离,实际上导致应用难于维护调试。每当修改标签行的时候,必须考虑是否破坏某个jQuery选择器。也许放宽对关注分离的信仰,我们也许会可能会减轻一些痛苦吧。(Perhaps if we relaxed our religIoUs devotion to separation of concerns,we Could relieve some of this pain?)这就迎来了第二个阶段的故事…

阶段2: 双向绑定

当前端开发看到Knockout和Angular的双向绑定的时候,这是一个启发。我们就在关注点分离与HTML中包含强大声明绑定之间摇摆。(Many of us tossed our religIoUs devotion to separation of concerns and embraced the power of declaring bindings in HTML.)当数据改变的时候,UI就更新。当UI改变的时候,数据也随之改变。如此干净,如此简单。

的确,每个类库和框架都有自己的一套实现方式,但是基本上做的都是同样的事情。简单看看几个流行框架中对数组迭代的简单例子:

//Angular
<div ng-repeat="user in users">

//Ember
{{#each user in users}}

//Knockout
data-bind="foreach: users"

这里好戏上演了。 几乎没有人意识到一个非常基本的问题: 这里我们实际上在HTML中放入了Javascript。这就不符合关注点分离的理念。上面所有的方法都做同样的一件事情: 通过添加额外专门的标>签,让HTML更加强大。这些标签实际上被解析为Javascript。我们最终非常舒服的将JS和HTML以此方式混合, 是时候介绍React,以及事情的另一面......

阶段3: JSX

React的JSX不是激进演变。它只是简单的认知成果: 作为一个行业,我们已经确定(有共识):-

HTML和Javascript是胞兄胞弟。

诚然,我们只是没有大声说出来而已。但是对Angular,Knockout和Ember的拥抱,让我们新的偏好更明确。上面已经确定,在HTML中写入数据绑定是一种有效的将JS注入HTML的方式。但是我们要混合,
为什么选择加强一个像HTML一样软弱涣散的技术呢。浏览器从出现的时候就松散的解析HTML。那么HTML是声明数据绑定,循环以及条件逻辑的逻辑基础吗?

Facebook认为Javascript是更加合适的处理这两种混合关系的逻辑和强大技术。 真谛在于(Facebook recognized that JavaScript was a more logical and powerful technology for handling these two intermingled concerns. The epiphany comes down to this):

Angular,Ember和Knockout是在HTML中放置JS。
而React是将HTML放置在JS中。

此举优势有多处,你还没有尝试React和JSX的话可能不会完全意识到。React的JSX在下面几个原因下比阶段2中所有类型的框架更优胜:

1. 编译时错误(Compile-time Errors)

如果你在HTML中打错字,一般来说你不知道哪里出了问题。很多情况下都是客户端运行时错误。例如,在使用angular的时候,如果将ng-repeat错误打成n-repeat,不会发生任何事情。同样对于Knockout来说如果将data-bind错误输入为data-bnd也是一样的。这两种情况,应用都会在运行时悄无声息的失败。那是相当沮丧的(frustrating)。

与此相比,在JSX中如果打印错误,根本不会编译。忘记闭合<li>标签? 你是否乐意在你HTML中打印错误的时候获得丰富的反馈呢?

ReactifyError: /components/header.js: Parse Error: Line 23: Expected corresponding JSX closing tag for li while parsing file: /components/header.js

使用JSX,这种详细的反馈最终成为现实!很难过分强调(overemphasize)这点上面到底优胜多少。这种快速反馈循环极大提高了生产力。正如在我的整洁代码课程中讨论的,精心设计的解决方案失败快
速(well-engineered solutions fail fast)。

2. 完全利用Javascript的强大功能(Leverage the Full Power of JavaScript)

在Javascript中组成标签,意味着在使用标签的时候可以尽情享受所有Javascript的强大能力,而不是那些HTML为中心的框架,例如Angular和Knockout,所提供的少量特殊子集所提供的能力。

客户端框架不应该需要用户学习声明循环和条件语句的专属语法。

React避免学习另外一种专属声明循环和条件语句方式的开销。正如你在阶段2中所见到的,每个双向绑定框架都利用自己特殊语法来实现这些。相比而言,JSX看起来几乎和HTML等价,它使用简单的面>相对象Javascript(ol Javascript)来实现诸如条件和循环的。在各自为政的Javascript生态系统中,不需要学历另外一种专属的数据绑定语法显然略胜一筹。(In an ecosystem as fragmented as JavaScript,not having to learn yet another proprietary data binding Syntax is a nice win.)

既然标签和相关联的javascript在同一个文件中书写, 很多IDE也会在你引用函数的时候提供一些智能支持。想象一下在面相HTML的框架中,引用函数的时候会有多么频繁的输入错误

结语(Final Thoughts)

JSX不是激进的思想。它是自然进化过程的产物。因此尽量不要抓狂。

JSX不是革命,而是进化。
JSX isn’t revolutionary. It’s evolutionary.

正如多数的进化形式,它是一种明智的改进。

是否想要了解更多? 那么请进入我的新课程,基于pluralsight.com网站上面的(多元视角)"使用React和Flux构建应用程序"

Check out my new course “Building Applications with React and Flux” on Pluralsight.

翻译原文地址:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom