Airbnb React/JSX 编码规范
Airbnb React/JSX 编码规范
算是最合理的React/JSX编码规范之一了
内容目录
- 基本规范
- Class vs React.createClass vs stateless
- 命名
- 声明模块
- 代码对齐
- 单引号还是双引号
- 空格
- 属性
- Refs引用
- 括号
- 标签
- 函数/方法
- 模块生命周期
- isMounted
Basic Rules 基本规范
- 每个文件只写一个模块.
- 但是多个无状态模块可以放在单个文件中. eslint:
react/no-multi-comp.
- 但是多个无状态模块可以放在单个文件中. eslint:
- 推荐使用JSX语法.
- 不要使用
React.createElement,除非从一个非JSX的文件中初始化你的app.
创建模块
Class vs React.createClass vs stateless
如果你的模块有内部状态或者是
refs, 推荐使用class extends React.Component而不是React.createClass,除非你有充足的理由来使用这些方法.
eslint:react/prefer-es6-classreact/prefer-stateless-function// badconst Listing = React.createClass({
// ...render() {
return <div>{this.state.hello}</div>;
}
}); // goodclass Listing extends React.Component {
// ...render() {
return <div>{this.state.hello}</div>;
}
}如果你的模块没有状态或是没有引用
refs, 推荐使用普通函数(非箭头函数)而不是类:// badclass 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>
); // goodfunction Listing({ hello }) {
return <div>{hello}</div>;
}
Naming 命名
- 扩展名: React模块使用
.jsx扩展名. - 文件名: 文件名使用驼峰式. 如,
ReservationCard.jsx. 引用命名: React模块名使用驼峰式命名,实例使用骆驼式命名. eslint:
react/jsx-pascal-case// badimport reservationCard from './ReservationCard'; // goodimport ReservationCard from './ReservationCard'; // badconst ReservationItem = <ReservationCard />; // goodconst reservationItem = <ReservationCard />;
模块命名: 模块使用当前文件名一样的名称. 比如
ReservationCard.jsx应该包含名为ReservationCard的模块. 但是,如果整个文件夹是一个模块,使用index.js作为入口文件,然后直接使用index.js或者文件夹名作为模块的名称:// badimport Footer from './Footer/Footer'; // badimport Footer from './Footer/index'; // goodimport Footer from './Footer';
高阶模块命名: 对于生成一个新的模块,其中的模块名
displayName应该为高阶模块名和传入模块名的组合. 例如, 高阶模块withFoo(), 当传入一个Bar模块的时候, 生成的模块名displayName应该为withFoo(Bar).为什么?一个模块的
displayName可能会在开发者工具或者错误信息中使用到,因此有一个能清楚的表达这层关系的值能帮助我们更好的理解模块发生了什么,更好的Debug.// 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相关的属性来用作其他的用途。
为什么?对于
style和className这样的属性名,我们都会默认它们代表一些特殊的含义,如元素的样式,CSS class的名称。在你的应用中使用这些属性来表示其他的含义会使你的代码更难阅读,更难维护,并且可能会引起bug。// bad
<MyComponent style="fancy" /> // good
<MyComponent variant="fancy" />
Declaration 声明模块
不要使用
displayName来命名React模块,而是使用引用来命名模块, 如 class 名称.// badexport default React.createClass({
displayName: 'ReservationCard',
// stuff goes here
}); // goodexport default class ReservationCard extends React.Component {
}
Alignment 代码对齐
遵循以下的JSX语法缩进/格式. eslint:
react/jsx-closing-bracket-location// bad
<Foo superLongParam="bar"anotherSuperLongParam="baz" /> // good, 有多行属性的话, 新建一行关闭标签
<FoosuperLongParam="bar"anotherSuperLongParam="baz"
/> // 若能在一行中显示, 直接写成一行
<Foo bar="bar" /> // 子元素按照常规方式缩进
<FoosuperLongParam="bar"anotherSuperLongParam="baz"
>
<Quux />
</Foo>
Quotes 单引号还是双引号
对于JSX属性值总是使用双引号(
"), 其他均使用单引号. eslint:jsx-quotes为什么? JSX属性 不能包括转译的引号, 因此在双引号里包括像
"don't"的属性值更容易输入. HTML属性也是用双引号,所以JSX属性也遵循同样的语法.// bad
<Foo bar='bar' /> // good
<Foo bar="bar" /> // bad
<Foo style={{ left: "20px" }} /> // good
<Foo style={{ left: '20px' }} />
Spacing 空格
总是在自动关闭的标签前加一个空格,正常情况下也不需要换行. eslint:
no-multi-spaces,react/jsx-space-before-closing// bad
<Foo/> // very bad
<Foo /> // bad
<Foo
/> // good
<Foo />不要在JSX
{}引用括号里两边加空格. eslint:react/jsx-curly-spacing// bad
<Foo bar={ baz } /> // good
<Foo bar={baz} />
Props 属性
JSX属性名使用骆驼式风格
camelCase.// bad
<FooUserName="hello"phone_number={12345678}
/> // good
<FoouserName="hello"phoneNumber={12345678}
/>如果属性值为
true, 可以直接省略. eslint:react/jsx-boolean-value// bad
<Foohidden={true}
/> // good
<Foohidden
/><img>标签总是添加alt属性. 如果图片以presentation(感觉是以类似PPT方式显示?)方式显示,alt可为空, 或者<img>要包含role="presentation". eslint:jsx-a11y/img-has-alt// 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" />不要在
alt值里使用如 "image", "photo", or "picture"包括图片含义这样的词, 中文也一样. eslint:jsx-a11y/img-redundant-alt为什么? 屏幕助读器已经把
img标签标注为图片了, 所以没有必要再在alt里说明了.// bad
<img src="hello.jpg" alt="Picture of me waving hello" /> // good
<img src="hello.jpg" alt="Me waving hello" />使用有效正确的 aria
role属性值 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" />不要在标签上使用
accessKey属性. eslint:jsx-a11y/no-access-key为什么? 屏幕助读器在键盘快捷键与键盘命令时造成的不统一性会导致阅读性更加复杂.
// bad
<div accessKey="h" /> // good
<div />避免使用数组的index来作为属性
key的值,推荐使用唯一ID. (为什么?)// bad
{todos.map((todo, index) =>
<Todo{...todo}key={index}
/>
)} // good
{todos.map(todo => (
<Todo{...todo}key={todo.id}
/>
))}
Refs
总是在Refs里使用回调函数. eslint:
react/no-string-refs// bad
<Fooref="myRef"
/> // good
<Fooref={ref => { this.myRef = ref; }}
/>
Parentheses 括号
将多行的JSX标签写在
()里. eslint:react/wrap-multilines// badrender() {
return <MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>;
} // goodrender() {
return (
<MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>
);
} // good, 单行可以不需要render() {
const body = <div>hello</div>;
return <MyComponent>{body}</MyComponent>;
}
Tags 标签
对于没有子元素的标签来说总是自己关闭标签. eslint:
react/self-closing-comp// bad
<Foo className="stuff"></Foo> // good
<Foo className="stuff" />如果模块有多行的属性, 关闭标签时新建一行. eslint:
react/jsx-closing-bracket-location// bad
<Foobar="bar"baz="baz" /> // good
<Foobar="bar"baz="baz"
/>
Methods 函数
使用箭头函数来获取本地变量.
function ItemList(props) {
return (
<ul>
{props.items.map((item, index) => ( <Item key={item.key} onClick={() => doSomethingWith(item.name, index)} /> ))}
</ul>
);
}当在
render()里使用事件处理方法时,提前在构造函数里把this绑定上去. eslint:react/jsx-no-bind为什么? 在每次
render过程中, 再调用bind都会新建一个新的函数,浪费资源.// badclass extends React.Component {
onClickDiv() {
// do stuff
} render() {
return <div onClick={this.onClickDiv.bind(this)} />
}
} // goodclass extends React.Component {
constructor(props) {
super(props); this.onClickDiv = this.onClickDiv.bind(this);
} onClickDiv() {
// do stuff
} render() {
return <div onClick={this.onClickDiv} />
}
}在React模块中,不要给所谓的私有函数添加
_前缀,本质上它并不是私有的.为什么?
_下划线前缀在某些语言中通常被用来表示私有变量或者函数。但是不像其他的一些语言,在JS中没有原生支持所谓的私有变量,所有的变量函数都是共有的。尽管你的意图是使它私有化,在之前加上下划线并不会使这些变量私有化,并且所有的属性(包括有下划线前缀及没有前缀的)都应该被视为是共有的。了解更多详情请查看Issue#1024, 和 #490 。// badReact.createClass({
_onClickSubmit() {
// do stuff
}, // other stuff
}); // goodclass extends React.Component {
onClickSubmit() {
// do stuff
} // other stuff
}在
render方法中总是确保return返回值. eslint:react/require-render-return// badrender() {
(<div />);
} // goodrender() {
return (<div />);
}
Ordering React 模块生命周期
class extends React.Component的生命周期函数:
- 可选的
static方法 constructor构造函数getChildContext获取子元素内容componentWillMount模块渲染前componentDidMount模块渲染后componentWillReceiveProps模块将接受新的数据shouldComponentUpdate判断模块需不需要重新渲染componentWillUpdate上面的方法返回true, 模块将重新渲染componentDidUpdate模块渲染结束componentWillUnmount模块将从DOM中清除, 做一些清理任务- 点击回调或者事件处理器 如
onClickSubmit()或onChangeDescription() render里的 getter 方法 如getSelectReason()或getFooterContent()- 可选的 render 方法 如
renderNavigation()或renderProfilePicture() renderrender() 方法
如何定义
propTypes,defaultProps,contextTypes, 等等其他属性...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稍有不同: eslint:react/sort-comp
displayName设定模块名称propTypes设置属性的类型contextTypes设置上下文类型childContextTypes设置子元素上下文类型mixins添加一些mixinsstaticsdefaultProps设置默认的属性值getDefaultProps获取默认属性值getInitialState或者初始状态getChildContextcomponentWillMountcomponentDidMountcomponentWillReceivePropsshouldComponentUpdatecomponentWillUpdatecomponentDidUpdatecomponentWillUnmount- clickHandlers or eventHandlers like
onClickSubmit()oronChangeDescription() - getter methods for
renderlikegetSelectReason()orgetFooterContent() - Optional render methods like
renderNavigation()orrenderProfilePicture() render
isMounted
不要再使用
isMounted. eslint:react/no-is-mounted为什么?
isMounted反人类设计模式:(), 在 ES6 classes 中无法使用, 官方将在未来的版本里删除此方法.
Airbnb React/JSX 编码规范的更多相关文章
- 【转】Airbnb React编码规范
Airbnb的编码规范是在业界非常流行的一套规范,而且它一直都在进化,推出最新技术的规范 原文:https://zhuanlan.zhihu.com/p/20616464 用更合理的方式书写React ...
- 【转】JavaScript 风格指南/编码规范(Airbnb公司版)
原文转自:http://blog.jobbole.com/79484/ Airbnb 是一家位于美国旧金山的公司,本文是其内部的 JavaScript 风格指南/编码规范,在 Github 上有 11 ...
- JavaScript 编码规范(中文/Airbnb公司版)
Airbnb 是一家位于美国旧金山的公司,本文是其内部的 JavaScript编码规范,写得比较全面,在 Github 上有 16,686 + Star,3,080 + fork,前端开发人员可参考. ...
- HTML/CSS/JS编码规范
最近整理了一份HTML/CSS/JS编码规范,供大家参考.目录:一.HTML编码规范二.CSS编码规范三.JS编码规范 一.HTML编码规范 1. img标签要写alt属性 根据W3C标准,img标签 ...
- 【go】脑补框架 Express beego tornado Flux reFlux React jsx jpg-ios出品
http://goexpresstravel.com/ 今天 Express 的作者 TJ Holowaychuk 发了一篇文章,正式宣告和 Node.js 拜拜了,转向 Go 语言. Go vers ...
- python编码规范、js编码规范及IDE的检查插件pylint/eslint等
一.python规范 参考:https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/的风格规范和语 ...
- Android的编码规范
一.Android编码规范 1.学会使用string.xml文件 在我看来,当一个文本信息出现的次数大于一次的时候就必须要使用string.xml 比如一个保存按钮 , 不规范写法: <Butt ...
- PHP 高级编程(1/5) - 编码规范及文档编写
PHP 高级程序设计学习笔记20140612 软件开发中的一个重要环节就是文档编写.他可以帮助未来的程序维护人员和使用者理解你在开发时的思路.也便于日后重新查看代码时不至于无从下手.文档还有一个重要的 ...
- 【原】JAVA SE编码规范
/* * 编码规范: * 1.所有的命名遵循"见名知意"的原则 * 2.所有的命名不允许使用汉字或拼音 * 3.Java的工程命名建议使用小写,比如:oa.crm.cms... * ...
随机推荐
- gokit 统计分析 M2M接入服务 OTA固件升级 硬件社交化
统计分析 M2M接入服务 OTA固件升级 硬件社交化 统计分析 为智能硬件定制的统计分析服务.只需添加入一行代码的集成工作,多维度的设备使用和用户行为数据就能自动统计出来. 演示 特色一:设备上线情 ...
- java并发编程笔记(四)——安全发布对象
java并发编程笔记(四)--安全发布对象 发布对象 使一个对象能够被当前范围之外的代码所使用 对象逸出 一种错误的发布.当一个对象还没构造完成时,就使它被其他线程所见 不安全的发布对象 某一个类的构 ...
- 转载! 一图读懂 SignalR
- 递归,装饰器,python常用内置方法
**递归** def calc(n): print(n) if int(n / 2) == 0: 条件判断 r ...
- 线性方程组迭代算法——Gauss-Seidel迭代算法的python实现
原理: 请看本人博客:线性方程组的迭代求解算法——原理 代码: import numpy as np max=100#迭代次数上限 Delta=0.01 m=2#阶数:矩阵为2阶 n=3#维数:3X3 ...
- shell脚本命令行参数里的空白符
看一个小脚本 #!/bin/bash #demonstarting the shift command count= while [ -n "$1" ] ; do echo &qu ...
- pytest-调整测试用例的执行顺序
场景:未考虑按自然顺序执行时,或想变更执行顺序,比如增加 数据的用例要先执行,再执行删除的用例.测试用例默认是按名 称顺序执行的. • 解决: • 安装:pip install pytest-orde ...
- dns轮训python
环境 python3 先安装dnspython模块 httpclient模块 resolver模块 pip install dnspython pip install hhtpclient pip i ...
- 笔记65 Spring Boot快速入门(五)
SpringBoot+JPA 一.什么是JPA? JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期 ...
- mysql的事务四个特性以及 事务的四个隔离级别
一.事务四大属性 分别是原子性.一致性.隔离性.持久性. 1,原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库, ...