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