React / JSX规范

基本规则

  • 每个文件只包含一个React组件。
  • 始终使用JSX语法。
  • React.createElement除非您从不是JSX的文件初始化应用程序,否则请勿使用。

Class vs React.createClass vs stateless

  • If you have internal state and/or refs, prefer class extends React.Component over React.createClass

    // bad
    const Listing = React.createClass({
      // ...
      render() {
        return <div>{this.state.hello}</div>;
      }
    });
    
    // good
    class Listing extends React.Component {
      // ...
      render() {
        return <div>{this.state.hello}</div>;
      }
    }

    And if you don’t have state or refs, prefer normal functions (not arrow functions) over classes:

    // bad
    class Listing extends React.Component {
      render() {
        return <div>{this.props.hello}</div>;
      }
    }
    
    // bad (relying on function name inference is discouraged)
    const Listing = ({ hello }) => (
      <div>{hello}</div>
    );
    
    // good
    function Listing({ hello }) {
      return <div>{hello}</div>;
    }

命名

  • 扩展:使用.jsxReact组件的扩展。

  • 文件名:使用PascalCase作为文件名。例如,ReservationCard.jsx

  • 参考命名:对其实例使用PascalCase用于React组件和camelCase。

  • // bad
    import reservationCard from './ReservationCard';
    
    // good
    import ReservationCard from './ReservationCard';
    
    // bad
    const ReservationItem = <ReservationCard />;
    
    // good
    const reservationItem = <ReservationCard />;
  • 组件命名:使用文件名作为组件名称。例如,ReservationCard.jsx应该有一个引用名称ReservationCard。但是,对于目录的根组件,请使用index.jsx文件名并使用目录名作为组件名称:

    // bad
    import Footer from './Footer/Footer';
    
    // bad
    import Footer from './Footer/index';
    
    // good
    import Footer from './Footer';
  • 高阶组件命名:使用高阶组件名称和传入组件名称的组合作为displayName生成组件的组合。例如,高次成分withFoo(),通过当组件Bar应该产生一个组分与displayNamewithFoo(Bar)

    // bad
    export default function withFoo(WrappedComponent) {
      return function WithFoo(props) {
        return <WrappedComponent {...props} foo />;
      }
    }
    
    // good
    export default function withFoo(WrappedComponent) {
      function WithFoo(props) {
        return <WrappedComponent {...props} foo />;
      }
    
      const wrappedComponentName = WrappedComponent.displayName
        || WrappedComponent.name
        || 'Component';
    
      WithFoo.displayName = `withFoo(${wrappedComponentName})`;
      return WithFoo;
    }
  • 道具命名:避免将DOM组件道具名称用于不同目的。

    // bad
    <MyComponent style="fancy" />
    
    // bad
    <MyComponent className="fancy" />
    
    // good
    <MyComponent variant="fancy" />

宣言

  • 不要displayName用于命名组件。而是通过引用命名组件。

  • // bad
    export default React.createClass({
      displayName: 'ReservationCard',
      // stuff goes here
    });
    
    // good
    export default class ReservationCard extends React.Component {
    }

对准

  • 遵循JSX语法的这些对齐样式。

  •  

    // 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>
    
    // bad
    {showButton &&
      <Button />
    }
    
    // bad
    {
      showButton &&
        <Button />
    }
    
    // good
    {showButton && (
      <Button />
    )}
    
    // good
    {showButton && <Button />}

行情

  • 始终"对JSX属性使用双引号(),但'对所有其他JS使用单引号()。

  •  

    // 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 />
  • 不要用空格填充JSX花括号。

    // bad
    <Foo bar={ baz } />
    
    // good
    <Foo bar={baz} />

道具

  • 始终使用camelCase作为道具名称。

// bad
<Foo
  UserName="hello"
  phone_number={12345678}
/>

// good
<Foo
  userName="hello"
  phoneNumber={12345678}
/>
  • 明确时,忽略道具的值true。

    // bad
    <Foo
      hidden={true}
    />
    
    // good
    <Foo
      hidden
    />
    
    // good
    <Foo hidden />
  • 始终alt<img>标签上包含道具。如果图像是表现形式,alt则可以是空字符串或<img>必须具有的字符串role="presentation"

    // 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道具中使用“图像”,“照片”或“图片”等字样。

    // bad
    <img src="hello.jpg" alt="Picture of me waving hello" />
    
    // good
    <img src="hello.jpg" alt="Me waving hello" />
  • Use only valid, non-abstract ARIA roles. eslint: jsx-a11y/aria-role

    // bad - not an ARIA role
    <div role="datepicker" />
    
    // bad - abstract ARIA role
    <div role="range" />
    
    // good
    <div role="button" />
  • 仅使用有效的非抽象ARIA角色

// bad
<div accessKey="h" />

// good
<div />
  • 不要accessKey在元素上使用。

避免使用数组索引作为keyprop,更喜欢稳定的ID

// bad
{todos.map((todo, index) =>
  <Todo
    {...todo}
    key={index}
  />
)}

// good
{todos.map(todo => (
  <Todo
    {...todo}
    key={todo.id}
  />
))}
  • 始终为所有不需要的道具定义显式defaultProp。
// 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,
};
  • 谨慎使用传播道具。

例外:

  • 代理道具并提升propTypes的HOC
function HOC(WrappedComponent) {
  return class Proxy extends React.Component {
    Proxy.propTypes = {
      text: PropTypes.string,
      isLoading: PropTypes.bool
    };

    render() {
      return <WrappedComponent {...this.props} />
    }
  }
}
  • 使用已知的显式道具传播对象。当使用Mocha的beforeEach构造测试React组件时,这可能特别有用。
export default function Foo {
  const props = {
    text: '',
    isPublished: false
  }

  return (<div {...props} />);
}

使用注意事项:尽可能过滤掉不必要的道具。另外,使用prop-types-exact来帮助防止错误。

// bad
render() {
  const { irrelevantProp, ...relevantProps  } = this.props;
  return <WrappedComponent {...this.props} />
}

// good
render() {
  const { irrelevantProp, ...relevantProps  } = this.props;
  return <WrappedComponent {...relevantProps} />
}

参考文献

  • 始终使用ref回调。

// bad
<Foo
  ref="myRef"
/>

// good
<Foo
  ref={(ref) => { this.myRef = ref; }}
/>

括弧

  • 当它们跨越多行时,在括号中包装JSX标记。

  • // bad
    render() {
      return <MyComponent variant="long body" foo="bar">
               <MyChild />
             </MyComponent>;
    }
    
    // good
    render() {
      return (
        <MyComponent variant="long body" foo="bar">
          <MyChild />
        </MyComponent>
      );
    }
    
    // good, when single line
    render() {
      const body = <div>hello</div>;
      return <MyComponent>{body}</MyComponent>;
    }

标签

  • 总是自我关闭没有孩子的标签

  • // bad
    <Foo variant="stuff"></Foo>
    
    // good
    <Foo variant="stuff" />
  • 如果组件具有多行属性,请在新行上关闭其标记。

    // bad
    <Foo
      bar="bar"
      baz="baz" />
    
    // good
    <Foo
      bar="bar"
      baz="baz"
    />

方法

  • 使用箭头函数关闭局部变量。

  • function ItemList(props) {
      return (
        <ul>
          {props.items.map((item, index) => (
            <Item
              key={item.key}
              onClick={() => doSomethingWith(item.name, index)}
            />
          ))}
        </ul>
      );
    }
  • 绑定构造函数中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} />;
      }
    }
  • 不要对React组件的内部方法使用下划线前缀。

    // bad
    React.createClass({
      _onClickSubmit() {
        // do stuff
      },
    
      // other stuff
    });
    
    // good
    class extends React.Component {
      onClickSubmit() {
        // do stuff
      }
    
      // other stuff
    }
  • 请务必在render方法中返回一个值。

    // bad
    render() {
      (<div />);
    }
    
    // good
    render() {
      return (<div />);
    }
  • 如何定义 propTypesdefaultPropscontextTypes, etc...

    import React from 'react';
    import PropTypes from 'prop-types';
    
    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开发时遵循的一些语法规范。如有不足之处,欢迎大家给出建议!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值