xiaomibaobao

Javascript Style Guide 之 React版本 翻译

Javascript Style Guide(-React) 翻译

此篇是react部分,由于不多,我就不写目录了。哈哈

基本规范

  • 一个模块使用一个文件最好(jsx),多个无状态组件可以使用一个文件。
  • 一般不使用React.creatElement。
  • 尽量使用JSX语法。

1. class XXX extends React.Component vs React.createClass

  • 正常应该使用ES6的方法:如果是个单独组件的话。
1
2
3
4
5
6
7
8
9
10
// good
export default class previewModal extends React.Component {sth.}
//bad
const Listing = React.createClass({
// ...
render() {
return <div>{this.state.hello}</div>;
}
});
  • 如果没有state 或者 refs ,直接使用一个正常function(既无状态组件) ,比使用class 更优!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// bad
class Listing extends React.Component {
render() {
return <div>{this.props.hello}</div>;
}
}
// bad 尽量使用function 关键字,react会根据函数名称推断
const Listing = ({ hello }) => (
<div>{hello}</div>
);
// good
function Listing({ hello }) {
return <div>{hello}</div>;
}
2.命名
  • 文件命名尽量使用PascalCase(一种计算机命名方法,所有和驼峰区别是所有单词首字母都大写)。
  • 文件扩展名尽量使用.jsx结尾,虽然.js结尾也可以使用。
  • 引用组件的时候,尽量让组件名和文件名一致,确保判断的准确性。
1
2
3
4
5
// bad
import reservationCard from './reservationCard';
// good
import ReservationCard from './ReservationCard';
  • 使用组件的命名 ,尽量使用驼峰,此时避免首字母大写。
1
2
3
4
5
// bad
const ReservationItem = <ReservationCard />;
// good
const reservationItem = <ReservationCard />;
  • 梯度性组件命名 ,尽量可以体现其父级组件或来源组件的名字,因为这些信息可能会被开发者工具或者错误信息捕捉到,有利于开发者做出判断并解决问题。
1
coming soon
  • 组件属性命名 ,请尽量避免使用JSX默认属性或者有特别含义的一些名字,比如style或者type等。
1
2
3
4
// bad
<MyComponent style="fancy" />
// good
<MyComponent variant="fancy" />

3 声明

  • 声明组件的时候,避免使用displayName这个属性来为组件声明,直接为组件命名最好。
1
2
3
4
5
6
7
8
9
// bad
export default React.createClass({
displayName: 'ReservationCard',
// stuff goes here
});
// good
export default class ReservationCard extends React.Component {
}

4 对齐

  • 对齐的时候应该使用JSX的对齐语法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// bad
<Foo superLongParam="bar"
anotherSuperLongParam="baz" />
// good
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
/>
// 如果这个是适合在一行显示,那就让他一行吧!
<Foo bar="bar" />
// 子集会看起来更加明确
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
>
<Quux />
</Foo>

5. 引号

  • 对于JSX的属性值,使用双引号,其他的JS中使用单引号比较好,因此在双引号里包括像 "don't"的属性值更容易输入.这是从常规的HTML属性中沿用的。
1
2
3
4
5
6
7
8
9
10
11
// bad
<Foo bar='bar' />
// good
<Foo bar="bar" />
// bad
<Foo style={{ left: "20px" }} />
// good
<Foo style={{ left: '20px' }} />

6.空格

-最好能在自闭合标签内使用一个空格来最作为结束,但在JSX的属性值内部引用括号的两端最好不要使用空格。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// bad
<Foo/>
// very bad
<Foo />
// bad
<Foo
/>
// good
<Foo />
// bad
<Foo bar={ baz } />
// good
<Foo bar={baz} />

7 属性相关

  • 在为属性命名的时候,尽量使用驼峰法不要使用下划线或者PascalCase。
1
2
3
4
5
6
7
8
9
10
11
// bad
<Foo
UserName="hello"
phone_number={12345678}
/>
// good
<Foo
userName="hello"
phoneNumber={12345678}
/>
  • 如果属性的属性值是boolean,并且是true的时候,请直接写属性名即可。
1
2
3
4
5
// bad
<Foo hidden={true} />
// good
<Foo hidden />
  • img标签添加alt属性,这个属性可以是空,也可以为img添加role="presentation"来表示这个图片是为展示而生。
1
2
3
4
5
6
7
8
9
10
11
// bad
<img src="hello.jpg" />
// good
<img src="hello.jpg" alt="Me waving hello" />
// good
<img src="hello.jpg" alt="" />
// good
<img src="hello.jpg" role="presentation" />
  • 不要再img 标签的alt属性添加类似”image”, “photo”, or “picture”的字样,因为没必要。img标签就是图片。
1
2
3
4
5
// bad
<img src="hello.jpg" alt="Picture of me waving hello" />
// good
<img src="hello.jpg" alt="Me waving hello" />
  • 如果用户可以读到,可以给用户添加ARIA属性(Accessible Rich Internet Application,可获取的网络富应用),这样会给残障人士带来便利,而不是给role属性添加相应的值。
1
2
3
4
5
6
7
// bad - not an ARIA role
<div role="datepicker" />
// bad - abstract ARIA role
<div role="range" />
// good
<div role="button" />
<input type="text" aria-label="用户名"/>
  • 尽量避免给元素添加accessKey这个属性。这会让一些快捷键重度患者迷惑。
bad
1
<div accessKey="h" />
  • 虽然不这样做也没什么关系,但是还是尽量给react中的数组型dom一个唯一的key值,这样会方便react找到并操作他们。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // bad
    {todos.map((todo, index) =>
    <Todo
    {...todo}
    key={index}
    />
    )}
    // good
    {todos.map(todo => (
    <Todo
    {...todo}
    key={todo.id}
    />
    ))}

-尽量把你元素/组件中需要进行PropTypes类型判断和不需要的分开来,这样避免遗漏类型判断并加速别人分析你的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// bad
function SFC({ foo, bar, children }) {
return <div>{foo}{bar}{children}</div>;
}
SFC.propTypes = {
foo: PropTypes.number.isRequired,
bar: PropTypes.string,
children: PropTypes.node,
};
// good
function SFC({ foo, bar }) {
return <div>{foo}{bar}</div>;
}
SFC.propTypes = {
foo: PropTypes.number.isRequired,
bar: PropTypes.string,
};
SFC.defaultProps = {
bar: '',
children: null,
};
  • 使用ref callback来定义ref,这个我真不懂了。。
1
2
3
4
5
// bad
<Foo ref="myRef" />
// good
<Foo ref={ref => { this.myRef = ref; }} />

8 圆括号

  • 如果return 的对象不止一行可以搞定,最好使用圆括号来包住他们。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 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>;
}

9.标签

  • 如果这个标签没有子集,使用单闭合标签是最好的。
1
2
3
4
5
// bad
<Foo className="stuff"></Foo>
// good
<Foo className="stuff" />
  • 如果你的组件有多行属性值的话,闭合他们的>符号最好另起一行。
1
2
3
4
5
6
7
8
9
10
// bad
<Foo
bar="bar"
baz="baz" />
// good
<Foo
bar="bar"
baz="baz"
/>

10 方法

  • 使用箭头函数来让函数内部方便的获取局部变量、全局变量、this
1
2
3
4
5
6
7
8
9
10
11
12
function ItemList(props) {
return (
<ul>
{props.items.map((item, index) => (
<Item
key={item.key}
onClick={() => doSomethingWith(item.name, index)}
/>
))}
</ul>
);
}
  • 如果需要给方法使用bind来传参的话,最好在构造器里做,如果在属性中绑定方法的话,bind会再新建一个函数,这样会浪费资源。
    ps : 但是我写的时候都是箭头函数,如果使用bind,也是在要传参数的情况下,这时候怎么在构造器中bind呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 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} />
}
}
  • 避免给私有变量加 _ 这样的前缀,因为在组件里,他们并不是私有的。JS并不原生支持私有属性。所有的属性都应该是公共的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// bad
React.createClass({
_onClickSubmit() {
// do stuff
},
// other stuff
});
// good
class extends React.Component {
onClickSubmit() {
// do stuff
}
// other stuff
}
  • render一定要return!
1
2
3
4
5
6
7
8
9
// bad
render() {
(<div />);
}
// good
render() {
return (<div />);
}

11 class extends React.Component时的顺序

  1. optional static methods
  2. constructor 启动函数构造
  3. getChildContext 获取子元素内容
  4. componentWillMount
  5. componentDidMount
  6. componentWillReceiveProps 组件将要接受新数据
  7. shouldComponentUpdate 判断组件是否需要重新渲染
  8. componentWillUpdate 上面的返回true才会走到这里
  9. componentDidUpdate
  10. componentWillUnmount
  11. 点击回调或者事件处理器 like onClickSubmit() or onChangeDescription()
  12. 拿到 render里的getter方法 类似于 getSelectReason() or getFooterContent()
  13. 可选的render方法 like renderNavigation() or renderProfilePicture()
  14. render

12 如何定义 propTypes, defaultProps, contextTypes等等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import React, { PropTypes } from 'react';
const propTypes = {
id: PropTypes.number.isRequired,
url: PropTypes.string.isRequired,
text: PropTypes.string,
};
const defaultProps = {
text: 'Hello World',
};
class Link extends React.Component {
static methodsAreOk() {
return true;
}
render() {
return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a>
}
}
Link.propTypes = propTypes;
Link.defaultProps = defaultProps;
export default Link;

React.createClass 的生命周期函数,

  • 这些函数比都是在class extends React.Component之前调用的。
    1. displayName
    2. propTypes
    3. contextTypes
    4. childContextTypes
    5. mixins

      不要使用isMounted,它在ES6中被移除了。。。

原文地址在这里

如果我实实在在的帮到您,可以点击打赏,请我喝一杯。