2 代码规范(JSX)
2. 代码规范(JSX)
2.1 命名规范
2.1.1 文件名
如果是文件,则使用大驼峰(PascalCase),如 MyComponent.jsx
如果是目录,则组件主入口文件命名为 index,如 index.jsx
ESLint规则: react/jsx-filename-extension
e.g. 举例
components
├── MyComponent.jsx
├── Footer
│ ├── other-file.jsx
│ └── index.jsx
2.1.2 引用命名
ESLint规则:
react/jsx-pascal-case
// React组件:使用大驼峰,如: MyComponent
// bad 不推荐
import myComponent from './MyComponent';
// good 推荐
import MyComponent from './MyComponent';
//组件实例:使用小驼峰,如: componentItem
// bad 不推荐
const ComponentItem = <MyComponent />;
// good 推荐
const componentItem = <MyComponent />;
// 对于文件夹中(如上面例子Footer),以`index.jsx`作为文件名的组件,则使用文件夹名字,来作为组件名字
// bad 不推荐
import Footer from './Footer/Footer';
import Footer from './Footer/index';
// good 推荐
import Footer from './Footer';
2.1.3 组件属性名
推荐使用React DOM 使用小驼峰式命名法来定义属性的名称,避免使用 HTML 属性名称的命名约定
// bad 不推荐
<MyComponent style='fancy' />
<MyComponent className='fancy' />
// good 推荐
<div onClick={this.handler} />
<MyComponent variant='fancy' />
2.2 对齐方式
遵循以下JSX语法的对齐风格
ESLint规则:
react/jsx-closing-bracket-location、react/jsx-closing-tag-location
// bad 不推荐
<Foo superLongParam='bar'
anotherSuperLongParam='baz' />
// good 推荐
<Foo
superLongParam='bar'
anotherSuperLongParam='baz'
/>
// 推荐 如果属性适合一行,则将其保持在同一行
<Foo bar='bar' />
// 子内容进行缩进
<Foo
superLongParam='bar'
anotherSuperLongParam='baz'
>
<Quux />
</Foo>
// bad 不推荐
{showButton &&
<Button />
}
// bad 不推荐
{
showButton &&
<Button />
}
// good 推荐
{showButton && (
<Button />
)}
// good 推荐
{showButton && <Button />}
// good 推荐
{someReallyLongConditional
&& anotherLongConditional
&& (
<Foo
superLongParam='bar'
anotherSuperLongParam='baz'
/>
)
}
// good 推荐
{someConditional ? (
<Foo />
) : (
<Foo
superLongParam='bar'
anotherSuperLongParam='baz'
/>
)}
2.3 空格
自闭合的标签前要加一个空格
ESLint规则:
no-multi-spaces、react/jsx-tag-spacing
// bad 不推荐
<Foo/>
<Foo />
<Foo
/>
// good 推荐
<Foo />
不要在 JSX 的花括号里边加空格
ESLint规则:
react/jsx-curly-spacing
// bad 不推荐
<Foo bar={ baz } />
// good 推荐
<Foo bar={baz} />
2.4 引号
对于 JSX 属性值总是使用双引号("), 其他均使用单引号(').
ESLint规则:
jsx-quotes
// bad 不推荐
<Foo bar="bar" />
<Foo style={{ left: "20px" }} />
// good 推荐
<Foo bar='bar' />
<Foo style={{ left: '20px' }} />
2.5 属性(Props)
属性名使用始终使用小驼峰,如果属性值是 React 组件,则使用大驼峰。
// bad 不推荐
<Foo
UserName='hello'
phone_number={12345678}
/>
// good 推荐
<Foo
userName='hello'
phoneNumber={12345678}
Component={SomeComponent}
/>
当属性值为true时可以省略
ESLint 规则:
react/jsx-boolean-value
// bad 不推荐
<Foo
hidden={true}
/>
// good 推荐
<Foo
hidden
/>
<Foo hidden />
<img> 标签上必须包含一个 alt 属性。且不要在alt中使用“image”、“photo”或“picture”等
ESLint规则:
jsx-a11y/img-redundant-alt、jsx-a11y/alt-text
// bad 不推荐
<img src='hello.jpg' />
<img src='hello.jpg' alt='Picture of me waving hello' />
// good 推荐
<img src='hello.jpg' alt='Me waving hello' />
// 如果图像是展示性的,alt 可以是空字符串,或 <img> 必须有 role='presentation'
<img src='hello.jpg' alt='' />
<img src='hello.jpg' role='presentation' />
避免使用数组的索引作为 key 属性值, 建议使用稳定的ID
ESLint规则:
react/no-array-index-key
原因:不使用稳定的 ID 会对性能产生副作用并且组件状态会出问题,是一种反模式
// bad 不推荐
{todos.map((todo, index) =>
<Todo
{...todo}
key={index}
/>
)}
// good 推荐
{todos.map(todo => (
<Todo
{...todo}
key={todo.id}
/>
))}
为所有的非必需属性定义使用 defaultProps 明确的默认值
// 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, children }) {
return <div>{foo}{bar}{children}</div>;
}
SFC.propTypes = {
foo: PropTypes.number.isRequired,
bar: PropTypes.string,
children: PropTypes.node
};
SFC.defaultProps = {
bar: '',
children: null
};
2.6 圆括号(Parentheses)
当 JSX 标签超过一行时使用圆括号包裹
ESLint规则:
react/wrap-multilines
// 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>
}
2.7 标签(Tags)
没有子元素的标签请自闭合
ESLint规则:
react/self-closing-comp
// bad 不推荐
<Foo className='stuff'></Foo>
// good 推荐
<Foo className='stuff' />
如果组件包含多行属性,在新的一行闭合标签
ESLint规则:
react/jsx-closing-bracket-location
// bad 不推荐
<Foo
bar='bar'
baz='baz' />
// good 推荐
<Foo
bar='bar'
baz='baz'
/>
2.8 方法(Methods)
使用箭头函数包裹本地变量
// good 推荐
function ItemList (props) {
return (
<ul>
{props.items.map((item, index) => (
<Item
key={item.key}
onClick={() => doSomethingWith(item.name, index)}
/>
))}
</ul>
);
}
在构造函数中为渲染方法绑定事件处理程序
ESLint规则:
react/jsx-no-bind
// bad 不推荐
class extends React.Component {
onClickDiv() {
// do stuff
}
render() {
return <div onClick={this.onClickDiv.bind(this)} />;
}
}
// very bad 非常不推荐
class extends React.Component {
onClickDiv = () => {
// do stuff
}
render() {
return <div onClick={this.onClickDiv} />
}
}
// good 推荐
class extends React.Component {
constructor(props) {
super(props);
this.onClickDiv = this.onClickDiv.bind(this);
}
onClickDiv() {
// do stuff
}
render() {
return <div onClick={this.onClickDiv} />;
}
}
类组件的内部方法不要使用下划线前缀
// bad 不推荐
class extends React.Component {
_onClickSubmit () {
// do stuff
}
// other stuff
}
// good 推荐
class extends React.Component {
onClickSubmit () {
// do stuff
}
// other stuff
}
确保在渲染(render)方法中返回一个值
ESLint规则:
require-render-return
// bad 不推荐
render () {
(<div />)
}
// good 推荐
render () {
return (<div />)
}
2.9 Hooks书写规范
- Hooks 只能应用于函数式组件中
- 只在 React 函数最顶层使用 Hooks
ESLint 规则:
react-hooks/rules-of-hooks、react-hooks/exhaustive-deps
原因:不要在循环、条件或嵌套函数中调用 Hook, 确保在你的 React 函数的最顶层调用他们
// bad 不推荐
// 在条件语句中使用 Hook 违反第一条规则
if (name !== '') {
useEffect(function persistForm() {
localStorage.setItem('formData', name);
});
}
// good 推荐
useEffect(function persistForm() {
// 将条件判断放置在 effect 中
if (name !== '') {
localStorage.setItem('formData', name);
}
});
2.10 类(class)组件定义
建议使用函数式组件配合 Hooks 来进行开发,但此处提供Class语法规则
// good
class extends React.Component {
constructor(props) {
super(props);
this.onClickDiv = this.onClickDiv.bind(this);
}
onClickDiv() {
// do stuff
}
render() {
return <div onClick={this.onClickDiv} />;
}
}
2.11 引用(Refs)
避免使用字符串引用,请使用回调函数作为引用
ESLint规则:
react/no-string-refs
// bad 不推荐
<Foo
ref='myRef'
/>
// good 推荐
<Foo
ref={ref => { this.myRef = ref }}
/>
**