我是这样看待 React 的

#1

说一下我对 React 整体的印象, 还有想一下对前端社区是有什么样的影响…

为什么我要关注 React

花这么多时间在 React 上边, 最开始是因为更新 DOM 的结果和我从前的期待很像:


当时我接触到 Angular 双向绑定, 就对照着公司用的 Handlebars 在思考模板引擎的问题
我发现模板引擎的 DOM 更新非常琐碎, 因此开始关注 MVVM 声称的自动更新的高效率,
除了 MVVM, Ractive.js 模块也做到, 而到了 React, 这个观念更加明确了.
从 Facebook 发布了 Flux 架构, 我就一直关注 React.

另一件事情是在国外社区 React 突然非常热门, 几个星期出现了好几个高质量的演讲
尤其是关于"单向数据流"架构的思考, 对我来说简直是醍醐灌顶,
在 Flux 架构当中, 非常明确要避免事件在各种 View 和 Model 交错的问题,
这些交错关系被理清之后, 编写应用就和后端写页面一样流程明确了.
所以我相信 React 以后会成为跟 Web Components 那样意义重大的技术.
而且国外社区已经证明了 React 非常棒, 相信很快会在国内火起来.

我觉得自己应该是前端开发者当中不多的非常关心函数式编程的人…
React 跟函数式响应式编程(Functional Reactive Programming) 有着千丝万缕的联系,
也许借着这个机会, 会有非常多函数式编程的思想能在 Web 开发当中转变为应用.
不过, 这些出风头的事情都是国外开发者在做… 真希望国内也有那样的水平
总之抱着这之类感想, 我非常希望 React 能在国内传播开来, 并且解决我开发当中遇到的问题.
现在有论坛了, 前面 @fraser 也举办过 meetup 了, 希望后面中文文档也能完成, 多带来点帮助

对比 jQuery 的意义

虽然 React 常常跟 Backbone, Angular 对比, 可实际上跟 jQuery 和 Web Components 对比更合适,
因为 React 没有完整处理 MVC 应用整体的架构, 而是仅仅是界面渲染的模块,
这个模块可以和 Backbone, Angular 搭配使用, 作为新的操作 DOM 的工具, 以代替 jQuery,
React 的功能, 一是维护 DOM 的更新和模块化, 二是封装了 DOM 的事件系统,
这两点也是人们使用 jQuery 重要原因. React 出现在双向绑定之后, 提供了更好的方案.

React 认为状态是特别容易出现很多 bug 的原因, 因为人们并不善于管理大量状态,
在 jQuery 当中, DOM 操作都是和 DOM 的状态有关的, 有时候其行为非常难预测.
相比之下 React 中提倡属性不变, 很好地避免了 jQuery 当中遇到的问题.
在 React 当中, DOM 的状态更新完全算法来完成, 开发者专注于数据部分,
当数据不变时 只有一种对应的界面, 因而程序有着更好的可预测性,

我个人觉得以后 React 可能像是现在大家用 jQuery 那样, 觉得理所当然.
而且编写应用时相比 jQuery, React 应用可以省却更多的代码, 效率也就更高.
至于能否完全替代 jQuery, 至少我在操作 DOM 当中进行替换已经能做到了.

关于 MVC

完整思考 MVC 在发布 Flux 时候才深入讲的, 不过目前没有官方的完整框架.
当时有很多评论说 Flux 其实和 MVC 没有差别, 虽然官方一直在努力把两者区分开来.
我认为 Flux 和前端 MV* 最重要的区别在于 Model 跟 View 的数量和其中的关系:

到了 Flux 当中, 除了名字改变了, 重要的是大量的 Model 归到了 Store, View 也统一了,
从而得到了所谓单向的数据流, 就是 Model 和 View 之间关系非常清晰了…
这样需要人为管理的状态就一下少了很多, 结果体现在开发应用的效率当中:

不过, 实际和已有的 MV* 框架对比的话, 我倾向认为 Flux 不是那么神的东西.
首先, Flux 框架的社区实现很多, 并没有哪一个一定说带来极高的开发效率,
真正带来开发效率区别的是自动更新 DOM, 而 Angular, Emberjs 在这方面也做非常棒.
这一方面来说, React 只是把自动更新 DOM 的门槛和成本降到了非常低而已
而在 Angular 和 Ember 中对界面 MVC 有很多经验, 这是 React 现在做不到的.

其他

对我来说, Angular 框架内容太多, 降低了和其他模块搭配使用的可能,
但是 React 作为模块, 其设计非常便于和其他的方案搭配使用, 甚至尝试新的方案编写应用,
当有这样的可能, 也许社区会出现更好的 Store 实现, 未来好的可能性会有很多…

目前我是这样看 React 的, 不代表以后不会有大的转变,
也有可能视角不够全面也不够深入, 这样要等其他同学挖更多的用法出来才行.
继续关注, 继续尝试用 React 做不同的东西…

7 Likes
#2

react还没看,先看了polymer,感觉相比angular这类框架,更容易入门,虽然目前看起来似乎只有ui,但觉得未来会有大工程化出现吧

#3

好像看到最近有个豆瓣 FM 的客户端使用 Polymer 写的, 一看觉得高大上.
我个人按照 React 社区的观点, 怀疑 Polymer 状态太多了不如 React 好写, anyway, 没真写过 Polymer.

#4

@fakefish @jiyinyiyong 看了polymer的各种要求,就没敢用了。

毕竟没多少实际在大项目中的应用。 React就不同了,慢慢的被很多大公司在用了。 学了就可以马上用到项目中了,更实际一点。

#5

同样不敢用 polymer, 对 Google 发起的技术革新都持审慎态度。

已经在公司项目中用着 react,踩坑比较多最近加班多,有时间好好分享一下

2 Likes
#6

昨天晚上想起来我有一点忘了写, 就是传入模块的数据的类型问题,

Polymer 更新的时候本来觉得很棒的, 但是看到模板里用的字符串有点心冷了.
动态语言存在问题就是缺乏强类型, 经常出现类型方面的错误不放一排查,
而 MVVM 的做法把表达式以字符串的形式放到了 HTML 当中, 也造成了排查上的困难.

在 React 里, 传入 Component 的数据有对应到 JS 当中的数据类型, 这一点看来就好多了.
有了数据类型, 要对代码进行抽象, 就可以参照 JS 当中的很多方案, 也就灵活很多了.
从这一点上, React 当作模板引擎用我认为是优于 Polymer 的方案… 当然, Polymer 要兼容 HTML 才那样做的.

#7

我来说说我的看法,因为之前了解过一些 Lisp,HTML 和 Lisp 的 S-expression 是非常类似的结构,比如:

<html>
  <body>
    <p>Hello world!</p>
  </body>
</html>

用 S-expression 来表达就是

(html
  (body
    (p "Hello world!")
  )
)

html, body, p 都可以看做是函数,于是我们编写页面其实就可以看做是各式各样的函数调用,我们也可以创建自己的函数,比如:

(html
  (body
    (accordion
      (panel
        (header "Panel1")
        (content "Content1")
      )
      (panel
        (header "Panel2")
        (content "Content2")
      )
    )
  )
)

我们还可以维持状态,加入逻辑,比如

(html
  (state
    (define foo true)
  )
  (body
    (if foo
      (p "foo is true")
      (p "foo is false")
    )
    (button 
      (onclick (lambda (set! foo false)))
      "Set false"
    )
  )
)

假设一个浏览器能够渲染这样的结构,那么点击按钮后,foo 变成了 false,浏览器重新对整个文档求值,渲染出结果即可。

React 的组件化思路和这是一脉相承的,virtual-dom 完成的就是这个浏览器的工作,我们可以用 js 函数来随心所欲的声明文档结构,封装自己的组件,添加状态和逻辑,不再受到模板的制约。

jshtml 本可以用 lisp数据即代码 的思想统一成相同的形式,而 Reactjs 统一了两者,声明 html 结构的过程也就是编写 js 代码的过程,文档里不再是一个个生硬的 div,而是能够交互的 accordiontabdialog

4 Likes
#8

没错,所以喜欢函数式编程的人看到 react 都会两眼发亮,可惜目前这种人还是比较少的。

#9

我想和 S-expression 的结构关系不大, HTML 的结构有着非常多的方式可以表述,
JS 当中的函数调用也能很好处理这个问题, 甚至对其中的对象结构支持更好一些.

React 之所以比以往的模板优秀, 一是因为 DOM 通过 Diff 更新, 二是因为 state 被抽象出来了,
每个 Component 的 state 在更新 DOM 时不会改变, 保证了用户定义其他的页面状态也保留了.
不过挺别扭的是 state 多少算是一个 mutable 的数据… 不清楚函数式编程里怎样看待的…

当然 Virtual DOM 带来的好处是不言而喻的.

#10

提到 S-expression 主要是因为 lisp 中的 数据即代码 的思想,传统的 html 形式更像是声明文档结构,像配置文件一样,转成 S-expression 之后,可以看出声明文档结构的过程实际上也可以看成是函数调用的过程,而这正是 React 所实现的组件化的思路。

#11

React.DOM.div({}, 'demo') 这样一次调用后, 实际上还是生成一个对象啊… 感觉和 DSL 差不多

#12

React 组件不只是一个 DSL,因为这种函数里面是可以实现内部状态和逻辑,相比传统的 html 中的 DOM 节点动态性强了太多

#13

稍微看了一下react,总觉得js里插html好蛋疼

1 Like
#14

所以我都直接写编译结果…

#15

直接写编译结果+1

#16

那么 0.12 后大家准备怎么直接写编译结果?@littlehaker

#17

我紧张了下, 其实没那么彻底, 内置标签还是能按原来写的,


昨天试了一下, 发现只是 require 模块的时候需要加上 createFactory, 其他可以先不改.
另外 React.render 要改下, 这个轻松.

#18

我们现在也在使用React来做页面中交互的部分,我们使用CoffeeScript来做的,所以Style上很好看。

{div, input, button, span, br, a, img, p} = React.DOM
...
render: ->
  div { className: "container" }, [
    p { className: "input-group" }, [
      label { htmlFor: "xxxxid" }, "Input"
      input { ... }
    ]
  ]
1 Like
#19

我也这样用过,不过我喜欢这样写:

render: ->
  (div className: "container", 
    (p className: "input-group", 
      (label htmlFor: "xxxxid", "Input")
      (input ...) 
    )
  )

更有 lisp 的感觉,哈哈

1 Like
#20

吼吼, Lisp 可是 写 )))))))