我们为什么需要 React?

7月13号更新, 其实我想问的不是angular跟react哪个好,哪个不好. 我想问的是,react的代码相对繁琐,那么在繁琐为代价的前提下为我们解…
关注者
1,588
被浏览
304,580

72 个回答

我们需要技术栈提供好用的模块化方式,可以是Web Component,可以是非Web Component的某种机制,不管什么库或者框架,我们需要技术赋予我们完成一个抽象,一次构建,多处复用的能力,并且这个过程不能太麻烦,不能做个很日常的抽象翻半天文档。

我们需要数据绑定,在各种粒度上真正实现事件驱动,因为这样我们就不用自己重复手写本质上并不依赖场景的从视图到数据从数据到视图的自动更新,否则我们就得自己操作DOM,优化DOM操作,还要自己维护状态,一自己维护状态,就要陷入状态同步的漩涡,浪费大量时间和精力。

我们需要技术栈隐藏掉平台的微妙差异,写一段代码可以真正实现跨平台,而不用我们自己纠结于那些本不该应用开发纠结的事,我们需要持续稳定的跨平台支持,最好的移植就是不用移植,这在商业上有很大的价值。

我们需要库或者框架好学,好用,从第一天起就能快速开发,而不是不得不经历几个月的学习曲线那种,因为大多数团队的程序员水平都存在梯度,我们不希望因为一个技术栈把初学水平的人挡在门外很久,理想的状态是技术本身能对招聘工作完全透明,同样的工期,同样的项目,随时找人都可以,招人的时候不用写得过于具体,只要会JavaScript就能快速上手,我们需要概念负担尽量少的技术栈,真正理解了Simplicity的技术。

我们希望技术栈有非常好的性能,性能的水平和垂直扩展性都很好,这样我们就不用项目写到一半回头去纠结应用开发团队很难解决的性能问题,我们需要在快速开发和基础性能之间平衡得很好的工具,而不是因为要强调某一方面而对另一方面关注太少的那些工具。

我们需要使用的工具有专业的团队或者社区持续地跟进,最好这些团队和社区自己就把自己的东西投入生产使用的技术,这样至少对我们来说风险就有起码的控制。我们不需要那些心血来潮,永远不成熟因为永远没有专门投入的技术。

我们需要那些普通人喜欢用,也用得好的技术。

React满足上面的一些方面,不满足另一些方面,和其他工具一样。你需要React,是因为两点

第一,你充分评估了你的项目,理解你要解决的问题是什么,是快速开发,性能,团队的ergonomics,多数情况下要解决的问题是多个要素的平衡
第二,你充分评估了React这个栈,理解它是解决你的具体问题的最佳工具,你真的理解了自己的场景中非用React不可的那些事情

如果你觉得React快所以需要,事实是React并没有那么快,尤其是大型应用,小型应用里快是不重要的,所有的框架都足够快。

如果你觉得React开发快所以需要,事实是React并一定是最好用的,尤其是当你考虑了团队的构成。

如果你觉得React是Facebook开发的所以需要,我的揣测是经历过一个社区adoption的高峰以后,Facebook未必能解决剩下的那1%的问题。

如果你觉得React Native很火所以需要,这或许是一个理由,但RN也不是唯一选择,从各方面评估,NativeScript这样的栈并不比RN坏多少,也许还稍微好一点。如果是大预算的商业开发,RN甚至不应该成为首选。

前面有个很让我认同的演讲, 思考的是人们怎么编程: 先为对应的问题建立一个模型, 然后用代码设计出一套 DSL, 再将代码进行运算以解决问题.

那么前端 UI 的更新当然是 MVC 或者 MV*, 也就是用户操作增量更新 Model, Model 更新怎样同步到 View.

比如 MVVM, 也就是 Angular 跟 Vue 采用的模式, 常说的双向绑定, 就是故意设计一些结构, 在 View 上操作时比如点击一个节点, 执行一个表达式更新一个位置, 双向绑定意味着界面和数据需要尽量做到一一对应, 不然的话, 从 View 操作的位置查找 Model 的更新的位置会有些麻烦(当然也不是没办法解决, 只是说这不是双向绑定为了解决的问题):

有了大体的模型, 然后就是做具体的实现, 后面还有填各种模型不适合解决的坑.

比如说 MVVM 前面那个 Object.observe 的事情, 后来总算据说因为性能方面问题不了了之了. 但回头看, 为了找到 Model 布局更新的位置, 各种方案也算辛苦了. 这样解决了 Model -> View 的问题, 在 View 到 Model 也是类似的情况, 所有赋值操作被代理了, 以便触发 View 的操作.

其实在我这种 FP 死党的眼里简直是不可思议, 本来还算简单的对象, 全部模拟 Atom 类型(脑补一个 Papi酱表情).

Flux 的套路呢稍有不同, 不是绑定了, View 更新会映射到一个 Action,至于 Action 怎么更新 Model, 自己写, 挺麻烦的, 不过这样的话其实就不用受到 ViewModel 跟 Model 之间对应关系的限制了. React 其实吸收了后端开发和函数式编程很多套路. 特别是函数式编程不可变数据. 至于 Redux, 在吸收了 Elm 的优点以后继续把概念往极端上推, 同时努力跟 ES6 大环境配合.


坑也不少, 首先 DOM Diff 就是为了适应方案而做的, 既然 DOM 是声明式的 DSL, 更新 DOM 的操作总要写, 于是通过 DOM Diff 生成出来. 整套方案其实开销不小, 于是从 FP 社区学了 Immutable 过来, 后面就是让很多人觉得眼花缭乱到无语的一大串东西.

其实看两个方案, JavaScript 和 DOM 两者都是被各种折腾的. MVVM 通过将数据变成 Observable 来变相实现 Reactive Programming, 也就是多份数据之间按照数据流自动同步, js 原生对象简直弱鸡, 干脆整个 hack 掉, 同时 HTML 也 Hack 成强大的 DSL 系统. 在 React 这边也差不多, DOM 需要做 Diff, 也需要依赖 Immutable, 干脆就是 JSX 上来. 对数据类型也不爽, 于是用整个 immutable 模块替换掉基础类型. 所以两个方案其实都把 js 那个了一遍, 建立自己的一整套 DSL.

MVVM 的坑我就不说了, 反正我不喜欢, 我也不会 Java 各种设计模式.

React 这边的问题也不小, 如果你熟悉点 FP 主流的语言, 一套 FP 的实现长成 React 社区这幅样子也真够累的了. 一切皆是表达式吗? js 设计的时候就不是. 不可变数据吗? 不是, 一般都可以改的. 结构复用方案内存优化吗? 没有, freeze 做不了, 只能自己做. 有隔离副作用的习惯吗? 整个语言遍布副作用. 异步抽象呢? 还在制定标准呢.

结果呢, React 得到的就是一个不上不下的方案, 一方面要用到艰涩的知识点去做高级的优化, 一方面要兼顾 JavaScript 巨大的生态. 跟着其他的事情层出不穷, 可变数据和不可变数据混在一起用怎么样? Component state 和 Closure variable 混合使用怎么样? 在函数式语言当中倾向于在语言层面增加限制, 避免大量出现 anti-pattern 影响全局, 但是 React 很难, 你教人写 JavaScript 还不让人随便写赋值, 哪有这样的道理?! 然后 React 只能延续这种混搭风了.

你可以找基于 FP 语言实现的 Flux 的套路, 对比一下 React 混搭的写法.

Elm

github.com/evancz/elm-t

Respo

github.com/respo-mvc/re

回到原来的问题, 为什么需要 React, 为什么 React 显得那么越来越奇葩. 我认为 React 背后的架构方案足够清晰也经得起时间考验, 这很重要. 为什么 React 越来越奇葩, 因为是混搭风.