prefer-const
, no-const-assign
// bad var a = 1; var b = 2; // good const a = 1; const b = 2;
no-var
jscs: disallowVar
// bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; }
⬆ 回到顶部javascript
no-new-object
// bad const item = new Object(); // good const item = {};
为何? 它们容许你在一个位置定义对象的全部属性html
function getKey(k) { return `a key named ${k}`; } // bad const obj = { id: 5, name: 'San Francisco', }; obj[getKey('enabled')] = true; // good const obj = { id: 5, name: 'San Francisco', [getKey('enabled')]: true, };
object-shorthand
// bad const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // good const atom = { value: 1, addValue(value) { return atom.value + value; }, };
object-shorthand
const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker, };
为何? 更容易知道哪些属性用了简写java
const anakinSkywalker = 'Anakin Skywalker'; const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, mayTheFourth: 4, anakinSkywalker, }; // good const obj = { lukeSkywalker, anakinSkywalker, episodeOne: 1, twoJediWalkIntoACantina: 2, episodeThree: 3, mayTheFourth: 4, };
quote-props
为何?通常来讲咱们主观上认为它更容易阅读。它改进了高亮语法,而且更容易被许多JS引擎优化node
// bad const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // good const good = { foo: 3, bar: 4, 'data-blah': 5, };
为何? 这些方法可能被 有问题的对象属性 隐藏 - 考虑
{hasOwnProperty: false}
- 或者, 对象多是一个空对象(Object.create(null)
)react
// bad console.log(object.hasOwnProperty(key)); // good console.log(Object.prototype.hasOwnProperty.call(object, key)); // best const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope. /* or */ const has = require('has'); … console.log(has.call(object, key));
// very bad const original = { a: 1, b: 2 }; const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ delete copy.a; // so does this // bad const original = { a: 1, b: 2 }; const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 } // good const original = { a: 1, b: 2 }; const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 } const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
⬆ 回到顶部git
no-array-constructor
// bad const items = new Array(); // good const items = [];
const someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
// bad const items = new Array(); // good const items = []; // bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good const itemsCopy = [...items];
array-callback-return
const foo = document.querySelectorAll('.foo'); const nodes = Array.from(foo);
⬆ 回到顶部es6
使用命名函数表达式,而不是函数声明。eslint: func-style
github
为何?函数声明是可被提高的, 这意味着太容易在 函数被定义以前 就引用它了。这会损害可读性和可维护性。若是你发现一个函数的定义是复杂的以至于它干扰到其他文件,,那么该提取成独立的模块。不要忘记命名表达式 - 匿名函数会使得更难在 Error's call stack 中找到问题(Discussion)ajax
// bad const foo = function () { }; // bad function foo() { } // good const foo = function bar() { };
wrap-iife
为何?一个当即调用的表达式是一个单一的单元express
// 当即调用的函数表达式 (IIFE) (() => { console.log('Welcome to the Internet. Please follow me.'); })();
永远不要在一个非函数代码块(if、while 等)中声明一个函数。把那个函数赋给一个变量。浏览器容许你这么作,但它们的解析表现不一致. eslint: no-loop-func
注意:ECMA-262 将 block
定义为语句列表 。 函数声明不是语句,Read ECMA-262's note on this issue.
// bad if (currentUser) { function test() { console.log('Nope.'); } } // good let test; if (currentUser) { test = () => { console.log('Yup.'); }; }
// bad function nope(name, options, arguments) { // ...stuff... } // good function yup(name, options, args) { // ...stuff... }
不要使用 arguments。能够选择 rest 语法 … 替代。 eslint: prefer-rest-params
为何?使用 … 能明确你要传入的参数。另外 rest 参数是一个真正的数组,而 arguments 是一个类数组。
// bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // good function concatenateAll(...args) { return args.join(''); }
// really bad function handleThings(opts) { // No! We shouldn't mutate function arguments. // Double bad: if opts is falsy it'll be set to an object which may // be what you want but it can introduce subtle bugs. opts = opts || {}; // ... } // still bad function handleThings(opts) { if (opts === void 0) { opts = {}; } // ... } // good function handleThings(opts = {}) { // ... }
// bad function handleThings(opts = {}, name) { // ... } // good function handleThings(name, opts = {}) { // ... }
no-param-reassign
为何? 操做做为参数传递的对象可能会在原始调用者中形成没必要要的变量反作用。
// bad function f1(obj) { obj.key = 1; }; // good function f2(obj) { const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; };
no-param-reassign
为何? 从新分配参数可能会致使 unexpected behavior, 特别是仇敌访问arguments对象的时候。它也可能致使优化问题,特别是在V8。
// bad function f1(a) { a = 1; } function f2(a) { if (!a) { a = 1; } } // good function f3(a) { const b = a || 1; } function f4(a = 1) { }
当你必须使用函数表达式(或传递一个匿名函数)时,使用箭头函数符号。eslint: prefer-arrow-callback
, arrow-spacing
为何?由于箭头函数创造了新的一个 this 执行环境(译注:参考 Arrow functions - JavaScript | MDN 和 ES6 arrow functions, syntax and lexical scoping),一般状况下都能知足你的需求,并且这样的写法更为简洁。
为何不?若是你有一个至关复杂的函数,你或许能够把逻辑部分转移到一个函数声明上。
// bad [1, 2, 3].map(function (x) { return x * x; }); // good [1, 2, 3].map((x) => { return x * x; });
若是一个函数适合用一行写出而且只有一个参数,那就把花括号、圆括号和 return 都省略掉。若是不是,那就不要省略. eslint: arrow-parens
, arrow-body-style
jscs: disallowParenthesesAroundArrowParam
, requireShorthandArrowFunctions
为何?语法糖。在链式调用中可读性很高。
// bad [1, 2, 3].map(number => { const nextNumber = number + 1; `A string containing the ${nextNumber}.`; }); // good [1, 2, 3].map(number => `A string containing the ${number}.`); // good [1, 2, 3].map((number) => { const nextNumber = number + 1; return `A string containing the ${nextNumber}.`; }); // good [1, 2, 3].map((number, index) => ({ [index]: number }));
以防表达式过长,利用括号让代码可读性更好
为何? 它能更清晰的展现函数的starts 和 ends.
// bad ['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod ) ); // good ['get', 'post', 'put'].map(httpMethod => ( Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod ) ));
no-confusing-arrow
// bad const itemHeight = item => item.height >= 256 ? item.largeSize : item.smallSize; // bad const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize; // good const itemHeight = item => (item.height >= 256 ? item.largeSize : item.smallSize); // good const itemHeight = (item) => { const { height, largeSize, smallSize } = item; return height >= 256 ? largeSize : smallSize; };
老是使用 class。避免直接操做 prototype
为何? 由于 class 语法更为简洁更易读。
// bad function Queue(contents = []) { this._queue = [...contents]; } Queue.prototype.pop = function() { const value = this._queue[0]; this._queue.splice(0, 1); return value; } // good class Queue { constructor(contents = []) { this._queue = [...contents]; } pop() { const value = this._queue[0]; this._queue.splice(0, 1); return value; } }
使用 extends 继承。
为何?由于 extends 是一个内建的原型继承方法而且不会破坏 instanceof。
// bad const inherits = require('inherits'); function PeekableQueue(contents) { Queue.apply(this, contents); } inherits(PeekableQueue, Queue); PeekableQueue.prototype.peek = function () { return this._queue[0]; } // good class PeekableQueue extends Queue { peek() { return this._queue[0]; } }
// bad Jedi.prototype.jump = function () { this.jumping = true; return true; }; Jedi.prototype.setHeight = function (height) { this.height = height; }; const luke = new Jedi(); luke.jump(); // => true luke.setHeight(20); // => undefined // good class Jedi { jump() { this.jumping = true; return this; } setHeight(height) { this.height = height; return this; } } const luke = new Jedi(); luke.jump() .setHeight(20);
为何? 重复声明类成员,那只会承认最后一个。 - having duplicates is almost certainly a bug.
// bad class Foo { bar() { return 1; } bar() { return 2; } } // good class Foo { bar() { return 1; } } // good class Foo { bar() { return 2; } }
老是使用import/export
Why? Modules are the future, let's start using the future now.
// bad const AirbnbStyleGuide = require('./AirbnbStyleGuide'); module.exports = AirbnbStyleGuide.es6; // ok import AirbnbStyleGuide from './AirbnbStyleGuide'; export default AirbnbStyleGuide.es6; // best import { es6 } from './AirbnbStyleGuide'; export default es6;
import的时候不要使用通配符
为何?这样能确保你只有一个默认 export。
// bad import * as AirbnbStyleGuide from './AirbnbStyleGuide'; // good import AirbnbStyleGuide from './AirbnbStyleGuide';
不要从 import 中直接 export
为何?虽然一行代码简洁明了,但让 import 和 export 各司其职让事情能保持一致。
// bad // filename es6.js export { es6 as default } from './airbnbStyleGuide'; // good // filename es6.js import { es6 } from './AirbnbStyleGuide'; export default es6;
import同一路径的,就一次性引入。eslint: no-duplicate-imports
为何?从同一路径导入多个行可能会使代码难以维护。
// bad import foo from 'foo'; // … some other imports … // import { named1, named2 } from 'foo'; // good import foo, { named1, named2 } from 'foo'; // good import foo, { named1, named2, } from 'foo';
不要export可变的绑定。eslint: import/no-mutable-exports
为何? 应该避免突变,通常来讲,但特别是当输出可变绑定。 虽然在某些特殊状况下可能须要此技术,但通常来讲,只应导出常量引用。
// bad let foo = 3; export { foo } // good const foo = 3; export { foo }
import/prefer-default-export
// bad export function foo() {} // good export default function foo() {}
将全部导入都放在非import语句之上。 eslint: import/first
为何? 保证他们一直在顶部能够预防 surprising behavior.
// bad import foo from 'foo'; foo.init(); import bar from 'bar'; // good import foo from 'foo'; import bar from 'bar'; foo.init();
不要使用 iterators,使用javascript的高阶函数例 替代for-in, for-of 。 eslint: no-iterator
no-restricted-syntax
为何?这强制咱们不变的规则。处理有返回值的纯函数比 处理它的反作用更容易。
纯函数的回调值更易读,这比它带来的反作用更重要。
Usemap()
/every()
/filter()
/find()
/findIndex()
/reduce()
/some()
/ ... to iterate over arrays,
andObject.keys()
/Object.values()
/Object.entries()
to produce arrays so you can iterate over objects.
const numbers = [1, 2, 3, 4, 5]; // bad let sum = 0; for (let num of numbers) { sum += num; } sum === 15; // good let sum = 0; numbers.forEach((num) => sum += num); sum === 15; // best (use the functional force) const sum = numbers.reduce((total, num) => total + num, 0); sum === 15;
如今还不要使用 generators
为何?由于它们如今还无法很好地编译到 ES5。 (目前Chrome 和 Node.js 的稳定版本都已支持 generators)
generator-star-spacing
// bad superPower = new SuperPower(); // good const superPower = new SuperPower();
使用 const 声明每个变量。eslint: one-var
为何?增长新变量将变的更加容易,并且你永远不用再担忧调换错
;
跟,
, 或引入仅标点符号差别。你还可使用debugger遍历每一个声明,而不是一次性跳过全部声明。
// bad const items = getItems(), goSportsTeam = true, dragonball = 'z'; // bad // (compare to above, and try to spot the mistake) const items = getItems(), goSportsTeam = true; dragonball = 'z'; // good const items = getItems(); const goSportsTeam = true; const dragonball = 'z';
将全部的 const 和 let 分组
为何?当你须要把已赋值变量赋值给未赋值变量时很是有用。
// bad let i, len, dragonball, items = getItems(), goSportsTeam = true; // bad let i; const items = getItems(); let dragonball; const goSportsTeam = true; let len; // good const goSportsTeam = true; const items = getItems(); let dragonball; let i; let length;
在你须要的地方给变量赋值,但请把它们放在一个合理的位置
为何?let 和 const 是块级做用域而不是函数做用域。
// bad - unnecessary function call function checkName(hasName) { const name = getName(); if (hasName === 'test') { return false; } if (name === 'test') { this.setName(''); return false; } return name; } // good function checkName(hasName) { if (hasName === 'test') { return false; } const name = getName(); if (name === 'test') { this.setName(''); return false; } return name; }
不要连接变量赋值
为何? 连接变量分配建立隐式全局变量。
// bad (function example() { // JavaScript interprets this as // let a = ( b = ( c = 1 ) ); // The let keyword only applies to variable a; variables b and c become // global variables. let a = b = c = 1; }()); console.log(a); // undefined console.log(b); // 1 console.log(c); // 1 // good (function example() { let a = 1; let b = a; let c = a; }()); console.log(a); // undefined console.log(b); // undefined console.log(c); // undefined // the same applies for `const`
避免使用一元增量和减量(++, --). eslint no-plusplus
为何? 根据eslint文档,一元增量和减量语句受到自动分号插入的影响,而且可能会致使应用程序中的值递增或递减的无声错误。 使用num + = 1而不是num ++或num ++这样的语句来改变你的值也更具表现力。 不容许一元增量和减量语句也会阻止您无心地预先递增/预减量值,这也会致使程序出现unexpected behavior。
// bad let array = [1, 2, 3]; let num = 1; num++; --num; let sum = 0; let truthyCount = 0; for(let i = 0; i < array.length; i++){ let value = array[i]; sum += value; if (value) { truthyCount++; } } // good let array = [1, 2, 3]; let num = 1; num += 1; num -= 1; const sum = array.reduce((a, b) => a + b, 0); const truthyCount = array.filter(Boolean).length;
eqeqeq
”
被计算为 false,不然为 trueif ([0] && []) { // true // an array (even an empty one) is an object, objects will evaluate to true }
// bad if (isValid === true) { // ...stuff... } // good if (isValid) { // ...stuff... } // bad if (name) { // ...stuff... } // good if (name !== '') { // ...stuff... } // bad if (collection.length) { // ...stuff... } // good if (collection.length > 0) { // ...stuff... }
/** ... */
做为多行注释。包含描述、指定全部参数和返回值的类型和值// bad // make() returns a new element // based on the passed in tag name // // @param {String} tag // @return {Element} element function make(tag) { // ...stuff... return element; } // good /** * make() returns a new element * based on the passed in tag name * * @param {String} tag * @return {Element} element */ function make(tag) { // ...stuff... return element; }
// bad const a = 0;// 我是注释 // bad //我是注释 const a = 0; // good // 我是注释 const a = 0;
给注释增长 FIXME 或 TODO 的前缀
帮助其余开发者快速了解这是一个须要复查的问题,或是给须要实现的功能提供一个解决方式。这将有别于常见的注释,由于它们是可操做的。使用 FIXME: -- need to figure this out
or TODO: -- need to implement
.
class Calculator { constructor() { // FIXME: shouldn't use a global here total = 0; } }
class Calculator { constructor() { // TODO: total should be configurable by an options param this.total = 0; } }
indent
space-before-blocks
keyword-spacing
space-infix-ops
// bad const x=y+5; // good const x = y + 5;
eol-last
newline-per-chained-call
no-whitespace-before-property
// bad $('#items').find('.selected').highlight().end().find('.open').updateCount(); // bad $('#items'). find('.selected'). highlight(). end(). find('.open'). updateCount(); // good $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount(); // bad const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true) .attr('width', (radius + margin) * 2).append('svg:g') .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') .call(tron.led); // good const leds = stage.selectAll('.led') .data(data) .enter().append('svg:svg') .classed('led', true) .attr('width', (radius + margin) * 2) .append('svg:g') .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') .call(tron.led); // good const leds = stage.selectAll('.led').data(data);
space-in-parens
, array-bracket-spacing
// bad function bar( foo ) { return foo; } // good function bar(foo) { return foo; } // bad if ( foo ) { console.log(foo); } // good if (foo) { console.log(foo); } // bad const foo = [ 1, 2, 3 ]; console.log(foo[ 0 ]); // good const foo = [1, 2, 3]; console.log(foo[0]);
object-curly-spacing
// bad const foo = {clark: 'kent'}; // good const foo = { clark: 'kent' };
避免一行代码超过100个字符,包括空格。eslint: max-len
为何? 确保可读性和可维护性。
javascript // bad const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // bad $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.')); // good const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // good $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' }, }) .done(() => console.log('Congratulations!')) .fail(() => console.log('You have failed this city.'));
⬆ 回到顶部
react/no-multi-comp
.React.createElement
,除非从一个非JSX的文件中初始化你的app.Class vs React.createClass vs stateless
refs
, 推荐使用 class extends React.Component
而不是 React.createClass
,除非你有充足的理由来使用这些方法.react/prefer-es6-class
react/prefer-stateless-function
// 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>; } }
若是你的模块没有状态或是没有引用refs
, 推荐使用普通函数(非箭头函数)而不是类:
// 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>; }
.jsx
扩展名.ReservationCard.jsx
.react/jsx-pascal-case
// bad import reservationCard from './ReservationCard'; // good import ReservationCard from './ReservationCard'; // bad const ReservationItem = <ReservationCard />; // good const reservationItem = <ReservationCard />;
ReservationCard.jsx
应该包含名为 ReservationCard
的模块. 可是,若是整个文件夹是一个模块,使用 index.js
做为入口文件,而后直接使用 index.js
或者文件夹名做为模块的名称:// bad import Footer from './Footer/Footer'; // bad import Footer from './Footer/index'; // good import 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" />
displayName
来命名React模块,而是使用引用来命名模块, 如 class 名称.// bad export default React.createClass({ displayName: 'ReservationCard', // stuff goes here }); // good export default class ReservationCard extends React.Component { }
react/jsx-closing-bracket-location
// bad <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // good, 有多行属性的话, 新建一行关闭标签 <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // 若能在一行中显示, 直接写成一行 <Foo bar="bar" /> // 子元素按照常规方式缩进 <Foo superLongParam="bar" anotherSuperLongParam="baz" > <Quux /> </Foo>
对于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' }} />
no-multi-spaces
, react/jsx-space-before-closing
// bad <Foo/> // very bad <Foo /> // bad <Foo /> // good <Foo />
{}
引用括号里两边加空格. eslint: react/jsx-curly-spacing
// bad <Foo bar={ baz } /> // good <Foo bar={baz} />
camelCase
.// bad <Foo UserName="hello" phone_number={12345678} /> // good <Foo userName="hello" phoneNumber={12345678} />
true
, 能够直接省略. eslint: react/jsx-boolean-value
// bad <Foo hidden={true} /> // good <Foo hidden />
<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" />
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 />
key
的值,推荐使用惟一ID. (为何?)// bad {todos.map((todo, index) => <Todo {...todo} key={index} /> )} // good {todos.map(todo => ( <Todo {...todo} key={todo.id} /> ))}
react/no-string-refs
// bad <Foo ref="myRef" /> // good <Foo ref={ref => { this.myRef = ref; }} />
()
里. 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, 单行能够不须要 render() { const body = <div>hello</div>; return <MyComponent>{body}</MyComponent>; }
react/self-closing-comp
// bad <Foo className="stuff"></Foo> // good <Foo className="stuff" />
react/jsx-closing-bracket-location
// 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()
里使用事件处理方法时,提早在构造函数里把 this
绑定上去. eslint: react/jsx-no-bind
为何? 在每次
render
过程当中, 再调用bind
都会新建一个新的函数,浪费资源.
// 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模块中,不要给所谓的私有函数添加 _
前缀,本质上它并非私有的.
为何?
_
下划线前缀在某些语言中一般被用来表示私有变量或者函数。可是不像其余的一些语言,在JS中没有原生支持所谓的私有变量,全部的变量函数都是共有的。尽管你的意图是使它私有化,在以前加上下划线并不会使这些变量私有化,而且全部的属性(包括有下划线前缀及没有前缀的)都应该被视为是共有的。了解更多详情请查看Issue #1024, 和 #490 。
// bad React.createClass({ _onClickSubmit() { // do stuff }, // other stuff }); // good class extends React.Component { onClickSubmit() { // do stuff } // other stuff }
render
方法中老是确保 return
返回值. eslint: react/require-render-return
// bad render() { (<div />); } // good render() { return (<div />); }
class extends React.Component
的生命周期函数:static
方法constructor
构造函数getChildContext
获取子元素内容componentWillMount
模块渲染前componentDidMount
模块渲染后componentWillReceiveProps
模块将接受新的数据shouldComponentUpdate
判断模块需不须要从新渲染componentWillUpdate
上面的方法返回 true
, 模块将从新渲染componentDidUpdate
模块渲染结束componentWillUnmount
模块将从DOM中清除, 作一些清理任务onClickSubmit()
或 onChangeDescription()
render
里的 getter 方法 如 getSelectReason()
或 getFooterContent()
renderNavigation()
或 renderProfilePicture()
render
render() 方法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
添加一些mixinsstatics
defaultProps
设置默认的属性值getDefaultProps
获取默认属性值getInitialState
或者初始状态getChildContext
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
onClickSubmit()
or onChangeDescription()
render
like getSelectReason()
or getFooterContent()
renderNavigation()
or renderProfilePicture()
render
不要再使用 isMounted
. eslint: react/no-is-mounted
为何? [
isMounted
反人类设计模式:()][anti-pattern], 在 ES6 classes 中没法使用, 官方将在将来的版本里删除此方法.
[anti-pattern]: https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html
Any feedback or complain or requests of you, please send email to Feedback