下面是我们部门总结的内部开发规范(试行版本),欢迎提意见。
部门FE React 组件开发规范
适用范围
部门FE 所有基于React开发的(包含fcui2)组件,欢迎提意见。
要求
必须:表示绝对要求这样做。
必须不:表示绝对不要求这样做。
应该/建议:表示一般情况下应该这样做,但是在某些特定情况下可以忽视这个要求。
应该不/不建议:表示一般情况下不应该这样做,但是在某些特定情况下可以忽视这个要求。
可以:表示这个要求完全是可选的,你可以这样做,也可以不这样做。
基本概念 [basic-concepts]
-
实例化生命周期
getDefaultPropsgetInitialStatecomponentWillMountrendercomponentDidMount
-
更新期生命周期
getInitialStatecomponentWillMountrendercomponentDidMount
-
运行期生命周期
componentWillReceivePropsshouldComponentUpdatecomponentWillUpdaterendercomponentDidUpdate
-
销毁期生命周期
componentWillUnmount
核心依赖 [deps](针对内部UI库)
必须在UI内只依赖React,underscore。
必须不在UI内部任何地方使用jQuery等直接操作DOM的库
JSX书写 [jsx]
必须命名JSX文件为.jsx.js。
必须使用PascalCase作为文件名。
必须只包含一个React Component在一个JSX文件中。
必须令文件名与所包含的React Component名字相同。
-
必须只能使用
React.createClass()来创建一个React Component。> 虽然ES6 Class和pure function都可以创建React Component, > 但ES6 Class不能使用mixin做扩展,与目前的扩展方法冲突; > Pure function较难掌握和管理。 必须使用JSX语法来生成组件的DOM片段。
必须不能在JSX中出现
React.createElement()。必须遵守下面示例中的DOM片段对齐方式。
// bad
<Foo superLongParam="bar"
anotherSuperLongParam="baz" />
// good
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
/>
// if props fit in one line then keep it on the same line
<Foo bar="bar" />
// children get indented normally
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
>
<Quux />
</Foo>
-
必须在DOM片段中使用双引号
"。> Why?JSX attributes [can't contain escaped quotes](http://eslint.org/docs/rules/jsx-quotes), so double quotes make conjunctions like `"don't"` easier to type. > Regular HTML attributes also typically use double quotes instead of single, so JSX attributes mirror this convention.
// bad
<Foo bar='bar' />
// good
<Foo bar="bar" />
// bad
<Foo style={{ left: "20px" }} />
// good
<Foo style={{ left: '20px' }} />
必须在自关闭标签前加一个空格。
// bad
<Foo/>
// very bad
<Foo />
// bad
<Foo
/>
// good
<Foo />
必须书写propTypes,规定每个可接受属性的类型,并对propTypes加以jsdoc说明。
必须使用camalCase来命名props。
// bad
<Foo
UserName="hello"
phone_number={12345678}
/>
// good
<Foo
userName="hello"
phoneNumber={12345678}
/>
必须当props的值为字面值true时,省略
={true}。
// bad
<Foo
hidden={true}
/>
// good
<Foo
hidden
/>
必须在DOM片段前后加一对括号
(),当DOM片段在一行以上时。
// bad
render() {
return <MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>;
}
// good
render() {
return (
<MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>
);
}
// good, when single line
render() {
const body = <div>hello</div>;
return <MyComponent>{body}</MyComponent>;
}
必须将组件写成自关闭标签,当组件没有children时。
// bad
<Foo className="stuff"></Foo>
// good
<Foo className="stuff" />
必须将关闭标签另起一行,当组件有多个props时。
// bad
<Foo
bar="bar"
baz="baz" />
// good
<Foo
bar="bar"
baz="baz"
/>
-
必须将bind handler到this的动作放到构造函数中。
> Why? A bind call in the render path creates a brand new function on every single render.
// bad
class extends React.Component {
onClickDiv() {
// do stuff
}
render() {
return <div onClick={this.onClickDiv.bind(this)} />
}
}
// good
class extends React.Component {
constructor(props) {
super(props);
this.onClickDiv = this.onClickDiv.bind(this);
}
onClickDiv() {
// do stuff
}
render() {
return <div onClick={this.onClickDiv} />
}
}
-
必须以如下的顺序排列JSX文件中的方法。
displayNamepropTypescontextTypeschildContextTypesmixinsstaticsdefaultPropsgetDefaultPropsgetInitialStategetChildContextcomponentWillMountcomponentDidMountcomponentWillReceivePropsshouldComponentUpdatecomponentWillUpdatecomponentDidUpdatecomponentWillUnmountclickHandlers or eventHandlers like
onClickSubmit()oronChangeDescription()getter methods for
renderlikegetSelectReason()orgetFooterContent()Optional render methods like
renderNavigation()orrenderProfilePicture()render
更多的通用组件规范 [general-guide]
[基本的JSX书写规范] (#jsx-jsx)基础上,更多的通用的React组件开发规范。
必须将所有UI组件实现为[Pure Renderer] (https://facebook.github.io/react/docs/pure-render-mixin.html)。
必须在props中存放所有外部导入的配置,包括显示控制参数、显示数据源、当前值(如果是input类型组件)、回调方法等。state相同时,对于一个特定的props,对应的组件展现结果唯一。
必须在state中存放组件运行期的状态,如输入框是否通过了校验、鼠标是否悬浮在按钮上等。props相同时,对于一组特定的state,对应的组件展现效果唯一。
不应该在state中存在[通过props运算来的属性] (https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html)。
建议父子关系的组件间传递props时,使用[rest-spread语法] (https://facebook.github.io/react/docs/transferring-props.html)。
必须仅在实例化生命周期中绑定window或body事件。
必须在销毁期生命周期中解绑window或body事件。
必须不允许在运行期生命周期中声明表达式函数。bind函数也不允许。
// bad
render() {
var cleverFunction = function () {};
// ...
}
// good
{
cleverFunction() {},
render() {
// just use this.cleverFunction
}
}
不建议在运行期生命周期中使用时间复杂度O(n2)及以上阶的算法。
必须不允许出现观察者模式,如自定义
addEventListener方法,或on,fire等。-
必须只能通过以下2种方法设置组件内部状态:
通过父组件的
render方法,改变子组件的props。通过子组件的
setState方法。
必须不允许为组件提供
setXXX方法来改变其内部状态,除非该setXXX方法中仅包含一个setState调用,且完成了一个充分复杂的state转换。必须为所有回调在
getDefaultProps给出空函数默认值_.noop。可以提供与组件内部数据结构紧密相关的操作方法。这些方法可以实现为一个纯函数,即只依赖其所有的参数来得到其结果。这些方法可以放在组件的
static域中。
博客地址
http://tangguangyao.github.io/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。