一个项目大多都是由一个团队来完成,如果没有统一的代码规范,那么每个人的代码必定会风格迥异。且不说会存在多个人同时开发同一模块的情况,即使是分工十分明晰的,等到要整合代码的时候也有够头疼的了。大多数情况下,并非程序中有复杂的算法或是复杂的逻辑,而是去读别人的代码实在是一件痛苦的事情。统一的风格使得代码可读性大大提高了,人们看到任何一段代码都会觉得异常熟悉。显然的,规范的代码在团队的合作开发中是非常有益而且必要的。
简要
- 要求说明
- 基本概念
- 通用规范
- JSX规范
- 组件规范
- 组件分类
- 组件结构
- 组件通信
要求说明
- 必须:表示绝对要求这样做。
- 必须不:表示绝对不要求这样做。
- 应该/建议:表示一般情况下应该这样做,但是在某些特定情况下可以忽视这个要求。
- 应该不/不建议:表示一般情况下不应该这样做,但是在某些特定情况下可以忽视这个要求。
- 可以:表示这个要求完全是可选的,你可以这样做,也可以不这样做。
基本概念
React生命周期
提供的一系列处理函数(钓子函数),这些函数会在组件生命周期的某个阶段调用。
- 创建期:getDefaultProps
创建期:getInitialState
在组件挂载前(即:创建期)调用一次,其返回值将做为this.state
的初始值创建期:componentWillMount
在初始化渲染执行之前被调用。如果在这个方法内调用setState()
方法,render()
方法将会收到更新后的state,也就是说这是做在组件渲染前最后一个修改state的机会。创建期:componentDidMount
一般在这个方法中使用this.getDOMNode()
方法访问原始DOM存在期:componentWillReceiveProps
组件感知到props属性改变会,会调用此方法。render()
方法将会在其后调用存在期:shouldComponentUpdate
在组件收到新的props
或state
。在这个方法中,我们可以访问组件的props和state属性,通过这两个属性可以确认组件是否需要更新,如果不需要更新,则返回false,则其后的方法将不会在执行
shouldComponentUpdate: function(nextProps, nextState) { |
存在期:componentWillUpdate
在收到新的props
或state
后调用,类似componentWillMount()
存在期:componentDidUpdate
在组件重新渲染后立即被调用,当我们需要在组件重新渲染后操作DOM则需要使用这个方法销毁&清理期:componentWillUnmount
是组件销毁&清理期唯一调用的方法,它会在组件从DOM中移除时被调用,这时我们可以清理一些状态或清理在componentDidMount
中创建的DOM元素。
通用规范
- 建议使用ES5原生方法操作数组
- 建议能用三元表达式,就不用
if else
,能用&&
,就不用三元表达式
// bad |
- 建议 代码块使用多行注释,语句使用单行注释,参数说明使用代码后注释
/** |
- 必须在DOM片段中使用双引号
"
, js中使用'
// bad |
JSX规范
- 建议遵守下面示例中的DOM片段对齐方式
// bad |
- 必须在自关闭标签前加一个空格
// bad |
- 必须在DOM片段前后加一对括号(),当DOM片段在一行以上时
// bad |
- 建议将组件写成自关闭标签,当组件没有
children
时
// bad |
组件规范
- 必须以
.jsx
结尾 - 必须只包含一个
React Component
- 必须只能使用
React.createClass()
来创建一个React Component
- 建议书写
propTypes
,规定每个可接受属性的类型,并对propTypes
加以说明,设置默认值,并申明在类外部
import React from 'react' |
- 必须使用
camalCase
来命名props
// bad |
- 建议当
props
的值为字面值true
时,省略={true}
// bad |
- 建议遵循如下的顺序排列JSX文件中的方法
render()
始终放在最后
React.createClass({ |
- 必须在state中只存放组件运行期的状态,保持
state
的简洁性 - 必须 仅在实例化生命周期中绑定window或body事件
- 必须在销毁期生命周期中解绑window或body事件
componentDidMount: function() { |
- 建议使用延展操作符为子组件传递属性
// bad |
- 建议复杂的render逻辑使用IIFE,在闭包中使用
if else
复杂的渲染逻辑中使用 if else
牺牲性能提升可读性
组件分类
约束好组件的职责,能让组件更好地解耦,知道什么功能是组件实现的,什么功能不需要实现
组件主要分为 通用组件(可复用组件)与 业务组件(一次性组件)
可复用组件实现通用的功能(不会因组件使用的位置、场景而变化)
- 命名与业务无关( Dialog/Toast/Button/Cell…)
- 只负责 UI展示、交互事件
- 尽量少的依赖,最大程序保持独立性,以确保在任何业务中复用
- 不依赖父组件,通过自定义事件与之交互
- 数据扁平化,使用props检验接收的数据
业务组件实现偏业务化的功能
- 获取数据
- 数据处理逻辑
- 引用可复用组件
通用组件:组件的最小单元,由业务组件引入使用,组装为业务组件,可分为布局组件、数据录入、数据展示、操作反馈等组件
业务组件:公共业务组件(多个业务复用) 与 页面业务组件(当前页面使用)
组件依赖
- 能用组件更可能少的依赖
- 组件的相关资源放置到同一个文件夹内(css、img)
组件结构
// ============== 依赖引用 |
组件通信
组件通信的三种方法:
- 使用props,构建通信链(嵌套深时,不适用)
- 使用模块内部的局部变量,在父组件初始化后,赋值给全局变量,子组件使用该变量访问父组件的属性,完成通信(变量不利用维护)
- 使用PubSub模式(利于解藕)
父子组件的通信
原则:props down, events up!
父组件通过 props
向下传递数据给子组件,子组件通过 events
给父组件发送消息,遵循单向数据流动的原则。
同级子组件的通信
使用 Pubsub 的事件发布订阅模式
在父组件中使用 Pubsub.subscribe()
订阅事件
在子组件中使用 Pubsub.publish()
触发事件,向父组件传递数据
在 componentWillUnmount
中使用 Pubsub.unsubscribe()
取消事件订阅