React-代码规范(jsx)-前端

479 阅读4分钟

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-locationreact/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-spacesreact/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-altjsx-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 }}
/>

**