Front

React.js最佳实践

虽然标题是最佳实践,其实是这一年来自己挖的各种坑,填了之后发现“其实这样写就不会有坑了”的总结…环境为桌面浏览器,因为目前后端还是Python为主,暂时没机会在NodeJS中使用各种便利的特征/插件。

代码顺序

定义一个React组件通常是包含以下代码:

以空行分割,有4个部分:

  • L2~3: propTypesmixins是可复用组件(Reusable Components)重要的两个对象,propTypes定义组件props的验证方式,相当于组件的说明,可以很快判断出该组件的用途,所以是放在第一个。
  • L5~9: 然后是生命周期(Lifecycle)相关方法,getDefaultProps/getInitialState是组件创建前触发,其他3个是组件变动时触发。顺序上会先执行getDefaultProps,所以getDefaultProps在getInitialState之前。
  • L11~12: 自定义的函数放在render前,命名以下划线开始,区分默认函数。
  • L14: 组件必须包含render方法,控制组件的显示,最重要且被执行得最晚所以放在最后。

JSX写法

直接使用JSXTransformer.js会收到warning(You are using the in-browser JSX transformer. Be sure to precompile your JSX for production),而且接近200KB的体积最好是省掉,JSX文件转换可以用react-tools(jsx)或Babel。jsx(0.13.3)有多余的空格,Babel默认的转换结果行数太多可读性不高,但官方已经停止维护react-tools了,所以用Babel。

多行JSX代码用return空格分成多行,可读性更好(偷懒的时候可以直接把HTML代码复制过来…)例如一个bootstrap的modal,用JSX来写:

条件判断用三元运算符和if都可以:

行内迭代用map,例如一系列checkbox:

PS: win7下virtualbox的linux中mount共享文件夹会检测不到文件改动,jsx的watch不生效。

用propTypes描述组件&大能的mixins

propTypes只在开发环境生效,所以目前只是用来描述组件,它干的事其实可以用Flow代替,以及最好不要试图改写它用来处理form的验证…

mixins是我目前使用频率最高的React特性了,例如很多地方会用到的拖动排序,写成mixins再调用:

简单组件用PureRenderMixin

setState会触发render,但如果state没有改变,也就没必要重新render。PureRenderMixin会自动比较state/props,避免重复render:

但如果sate/props数据比较复杂(例如count不是数字,而是Object)会误判,官方推荐使用immutable objects来处理。

尽量不要在子组件中操作父组件

React中,父组件访问子组件可以通过ref,但从子组件访问父组件就比较麻烦了。我之前是给子组件传递一个名为parentInstance的prop指向父组件,然后在子组件中对父组件进行setState的操作,这么写其实很乱,也容易产生Bug。

单向数据流是Flux的重要概念,同样对于组件结构来说,父组件通过props传递数据之后,如果子组件再去对它进行setState,等于又转回去了。而且props通常都是父组件的state,调用setState还会导致子组件被重置(除非加了PureRenderMixin)。

这也是一个教训,刚开始先完成子组件的各种逻辑,结果写父组件的时候才发现很多地方不能用,逻辑也一片混乱,都要重写。之后就长记性了,根据数据流来写,从父到子,可以避免很多问题。

render除了放JSX也可以写逻辑

例如有一个表单,创建记录时直接显示表单,编辑记录时用prop传递表单中字段的值,需要对prop做预处理。刚开始我是把这些逻辑都写在componentWillReceiveProps里,后来发现很多需求都要改3个地方:componentWillMount/componentWillReceiveProps/render,而且componentWillMount/componentWillReceiveProps有些逻辑是一样的。

现在尝试把这些类似的逻辑写在一个单独的函数里,放在render中调用——如果逻辑简单都不分函数了,直接写在render里——这样就简单&清晰了许多,某个地方显示出错也可以直奔render,不用再去检查componentWillReceiveProps了。当然,获取/设置数据的逻辑是不能写在render里的,render中的ajax配setState等于死循环。

开发者工具可以解决很多Debug问题

除了链接没什么需要说的,Firefox熬出头了… https://github.com/facebook/react-devtools/releases

Afterword

目前我在公司里的所有项目都用了React,因为企业内部的需求重合度很高,写好一套可复用组件就无往不利了。只是目前还没有在2C的项目的前台用过,所以对于React的高性能,感触没那么深。总体来说React学习成本低(用过JS的MVC框架上手无难度),配套设施全(hot-loader/relay/GraphQL),设计理念新(Flux),遇到的坑也都是自己挖的,目前来看发展前景不错,已暂定为Backbone之后的主攻框架了。

Leave a Reply

Your email address will not be published. Required fields are marked *