[关闭]
@chris-ren 2016-04-27T07:59:02.000000Z 字数 19618 阅读 1094

前端编码规范

ECMAScript JavaScript react 规范


本文主要介绍JavaScript编码规范以及基于JavaScript规范,针对ES6和React拟定的相关规范约定。
原文链接(需要查看详细信息请参照):https://github.com/airbnb/javascript

JavaScript规范

目录

1.类型
2.对象
3.数组
4.字符串
5.函数
6.属性
7.变量
8.条件表达式和等号
9.块
10.注释
11.空白
12.逗号
13.分号
14.类型转换
15.命名约定
16.存取器
17.事件

类型

基本类型:访问基本类型时,应该直接操作类型值
- string
- number
- boolean
- null
- undefined

  1. var foo = 1,
  2. bar = foo;
  3. bar = 9;
  4. console.log(foo, bar); // => 1, 9

复杂类型:访问复杂类型时,应该操作其引用
- object
- array
- function

  1. var foo = [1, 2],
  2. bar = foo;
  3. bar[0] = 9;
  4. console.log(foo[0], bar[0]); // => 9, 9

对象

  1. // bad
  2. var superman = {
  3. class: 'superhero',
  4. default: { clark: 'kent' },
  5. private: true
  6. };
  7. // good
  8. var superman = {
  9. klass: 'superhero',
  10. defaults: { clark: 'kent' },
  11. hidden: true
  12. };

数组

  1. // bad
  2. var items = new Array();
  3. // good
  4. var items = [];
  1. var someStack = [];
  2. // bad
  3. someStack[someStack.length] = 'abracadabra';
  4. // good
  5. someStack.push('abracadabra');
  1. var len = items.length,
  2. itemsCopy = [],
  3. i;
  4. // bad
  5. for (i = 0; i < len; i++) {
  6. itemsCopy[i] = items[i];
  7. }
  8. // good
  9. itemsCopy = items.slice();
  1. function trigger() {
  2. var args = [].slice.apply(arguments);
  3. ...
  4. }

字符串

  1. // bad
  2. var name = "Bob Parr";
  3. // good
  4. var name = 'Bob Parr';
  5. // bad
  6. var fullName = "Bob " + this.lastName;
  7. // good
  8. var fullName = 'Bob ' + this.lastName;
  1. // bad
  2. var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
  3. // bad
  4. var errorMessage = 'This is a super long error that \
  5. was thrown because of Batman. \
  6. When you stop to think about \
  7. how Batman had anything to do \
  8. with this, you would get nowhere \
  9. fast.';
  10. // good
  11. var errorMessage = 'This is a super long error that ' +
  12. 'was thrown because of Batman.' +
  13. 'When you stop to think about ' +
  14. 'how Batman had anything to do ' +
  15. 'with this, you would get nowhere ' +
  16. 'fast.';
  1. var items,
  2. messages,
  3. length, i;
  4. messages = [{
  5. state: 'success',
  6. message: 'This one worked.'
  7. },{
  8. state: 'success',
  9. message: 'This one worked as well.'
  10. },{
  11. state: 'error',
  12. message: 'This one did not work.'
  13. }];
  14. length = messages.length;
  15. // bad
  16. function inbox(messages) {
  17. items = '<ul>';
  18. for (i = 0; i < length; i++) {
  19. items += '<li>' + messages[i].message + '</li>';
  20. }
  21. return items + '</ul>';
  22. }
  23. // good
  24. function inbox(messages) {
  25. items = [];
  26. for (i = 0; i < length; i++) {
  27. items[i] = messages[i].message;
  28. }
  29. return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
  30. }

函数

  1. // 匿名函数表达式
  2. var anonymous = function() {
  3. return true;
  4. };
  5. // 有名函数表达式
  6. var named = function named() {
  7. return true;
  8. };
  9. // 立即调用函数表达式
  10. (function() {
  11. console.log('Welcome to the Internet. Please follow me.');
  12. })();
  1. // bad
  2. if (currentUser) {
  3. function test() {
  4. console.log('Nope.');
  5. }
  6. }
  7. // good
  8. if (currentUser) {
  9. var test = function test() {
  10. console.log('Yup.');
  11. };
  12. }
  1. // bad
  2. function nope(name, options, arguments) {
  3. // ...stuff...
  4. }
  5. // good
  6. function yup(name, options, args) {
  7. // ...stuff...
  8. }

属性

  1. var luke = {
  2. jedi: true,
  3. age: 28
  4. };
  5. function getProp(prop) {
  6. return luke[prop];
  7. }
  8. var isJedi = getProp('jedi');

变量

  1. // bad
  2. superPower = new SuperPower();
  3. // good
  4. var superPower = new SuperPower();
  1. // bad
  2. var items = getItems();
  3. var goSportsTeam = true;
  4. var dragonball = 'z';
  5. // good
  6. var items = getItems(),
  7. goSportsTeam = true,
  8. dragonball = 'z';
  1. // bad
  2. var i, len, dragonball,
  3. items = getItems(),
  4. goSportsTeam = true;
  5. // bad
  6. var i, items = getItems(),
  7. dragonball,
  8. goSportsTeam = true,
  9. len;
  10. // good
  11. var items = getItems(),
  12. goSportsTeam = true,
  13. dragonball,
  14. length,
  15. i;
  1. / bad
  2. function() {
  3. test();
  4. console.log('doing stuff..');
  5. //..other stuff..
  6. var name = getName();
  7. if (name === 'test') {
  8. return false;
  9. }
  10. return name;
  11. }
  12. // good
  13. function() {
  14. var name = getName();
  15. test();
  16. console.log('doing stuff..');
  17. //..other stuff..
  18. if (name === 'test') {
  19. return false;
  20. }
  21. return name;
  22. }
  23. // bad
  24. function() {
  25. var name = getName();
  26. if (!arguments.length) {
  27. return false;
  28. }
  29. return true;
  30. }
  31. // good
  32. function() {
  33. if (!arguments.length) {
  34. return false;
  35. }
  36. var name = getName();
  37. return true;
  38. }

条件表达式和等号

  1. if ([0]) {
  2. // true
  3. // An array is an object, objects evaluate to true
  4. }
  1. // bad
  2. if (name !== '') {
  3. // ...stuff...
  4. }
  5. // good
  6. if (name) {
  7. // ...stuff...
  8. }
  9. // bad
  10. if (collection.length > 0) {
  11. // ...stuff...
  12. }
  13. // good
  14. if (collection.length) {
  15. // ...stuff...
  16. }

  1. // bad
  2. if (test)
  3. return false;
  4. // good
  5. if (test) return false;
  6. // good
  7. if (test) {
  8. return false;
  9. }
  10. // bad
  11. function() { return false; }
  12. // good
  13. function() {
  14. return false;
  15. }

注释

  1. // bad
  2. // make() returns a new element
  3. // based on the passed in tag name
  4. //
  5. // @param <String> tag
  6. // @return <Element> element
  7. function make(tag) {
  8. // ...stuff...
  9. return element;
  10. }
  11. // good
  12. /**
  13. * make() returns a new element
  14. * based on the passed in tag name
  15. * * @param <String> tag
  16. * @return <Element> element
  17. */
  18. function make(tag) {
  19. // ...stuff...
  20. return element;
  21. }
  1. // bad
  2. var active = true; // is current tab
  3. // good
  4. // is current tab
  5. var active = true;
  6. // bad
  7. function getType() {
  8. console.log('fetching type...');
  9. // set the default type to 'no type'
  10. var type = this._type || 'no type';
  11. return type;
  12. }
  13. // good
  14. function getType() {
  15. console.log('fetching type...');
  16. // set the default type to 'no type'
  17. var type = this._type || 'no type';
  18. return type;
  19. }
  1. function Calculator() {
  2. // FIXME: shouldn't use a global here
  3. total = 0;
  4. return this;
  5. }
  1. function Calculator() {
  2. // TODO: total should be configurable by an options param
  3. this.total = 0;
  4. return this;
  5. }

空白

  1. // bad
  2. function() {
  3. ∙∙∙∙var name;
  4. }
  5. // bad
  6. function() {
  7. var name;
  8. }
  9. // good
  10. function() {
  11. ∙∙var name;
  12. }
  1. // bad
  2. function test(){
  3. console.log('test');
  4. }
  5. // good
  6. function test() {
  7. console.log('test');
  8. }
  9. // bad
  10. dog.set('attr',{
  11. age: '1 year',
  12. breed: 'Bernese Mountain Dog'
  13. });
  14. // good
  15. dog.set('attr', {
  16. age: '1 year',
  17. breed: 'Bernese Mountain Dog'
  18. });
  1. // bad
  2. var x=y+5;
  3. // good
  4. var x = y + 5;

逗号

  1. // bad
  2. var once
  3. , upon
  4. , aTime;
  5. // good
  6. var once,
  7. upon,
  8. aTime;
  9. // bad
  10. var hero = {
  11. firstName: 'Bob'
  12. , lastName: 'Parr'
  13. , heroName: 'Mr. Incredible'
  14. , superPower: 'strength'
  15. };
  16. // good
  17. var hero = {
  18. firstName: 'Bob',
  19. lastName: 'Parr',
  20. heroName: 'Mr. Incredible',
  21. superPower: 'strength'
  22. };
  1. // bad
  2. var hero = {
  3. firstName: 'Kevin',
  4. lastName: 'Flynn',
  5. };
  6. var heroes = [
  7. 'Batman',
  8. 'Superman',
  9. ];
  10. // good
  11. var hero = {
  12. firstName: 'Kevin',
  13. lastName: 'Flynn'
  14. };
  15. var heroes = [
  16. 'Batman',
  17. 'Superman'
  18. ];

分号

  1. // bad
  2. (function() {
  3. var name = 'Skywalker'
  4. return name
  5. })()
  6. // good
  7. (function() {
  8. var name = 'Skywalker';
  9. return name;
  10. })();
  11. // good
  12. ;(function() {
  13. var name = 'Skywalker';
  14. return name;
  15. })();

类型转换

  1. var inputValue = '4';
  2. // bad
  3. var val = new Number(inputValue);
  4. // bad
  5. var val = +inputValue;
  6. // bad
  7. var val = inputValue >> 0;
  8. // bad
  9. var val = parseInt(inputValue);
  10. // good
  11. var val = Number(inputValue);
  12. // good
  13. var val = parseInt(inputValue, 10);
  14. // good
  15. /**
  16. * parseInt was the reason my code was slow.
  17. * Bitshifting the String to coerce it to a
  18. * Number made it a lot faster.
  19. */
  20. var val = inputValue >> 0;
  1. var age = 0;
  2. // bad
  3. var hasAge = new Boolean(age);
  4. // good
  5. var hasAge = Boolean(age);
  6. // good
  7. var hasAge = !!age;

命名约定

  1. // bad
  2. this.__firstName__ = 'Panda';
  3. this.firstName_ = 'Panda';
  4. // good
  5. this._firstName = 'Panda';

存取器

  1. // bad
  2. if (!dragon.age()) {
  3. return false;
  4. }
  5. // good
  6. if (!dragon.hasAge()) {
  7. return false;
  8. }
  1. function Jedi(options) {
  2. options || (options = {});
  3. var lightsaber = options.lightsaber || 'blue';
  4. this.set('lightsaber', lightsaber);
  5. }
  6. Jedi.prototype.set = function(key, val) {
  7. this[key] = val;
  8. };
  9. Jedi.prototype.get = function(key) {
  10. return this[key];
  11. };

事件

  1. // bad
  2. $(this).trigger('listingUpdated', listing.id);
  3. ...
  4. $(this).on('listingUpdated', function(e, listingId) {
  5. // do something with listingId
  6. });
  7. // good
  8. $(this).trigger('listingUpdated', { listingId : listing.id });
  9. ...
  10. $(this).on('listingUpdated', function(e, data) {
  11. // do something with data.listingId
  12. });

针对ES6相关内容的规范

1.声明 Declarations
2.字符串 Strings
3.解构 Destructuring
4.数组 Arrays
5.函数 Functions
6.类 Classes
7.模块 Modules

声明

•1.1 变量

  1. // bad
  2. const variables;
  3. const globalObj = null; // 不是常量
  4. let globalObj = null;
  5. for (var i = 0; i < 5; i++) {
  6. console.log(i);
  7. }
  8. console.log(i); // 4
  9. // good
  10. let variables;
  11. var globalObj = null;
  12. for (let i = 0; i < 5; i++) {
  13. console.log(i);
  14. }
  15. console.log(i); // ReferenceError: i is not defined

•1.2 常量

  1. // bad
  2. let someNum = 123;
  3. const AnotherStr = '不变的字符串';
  4. let arr = ['不', '变', '数', '组'];
  5. var ANOTHER_OBJ = {
  6. '不变对象': true
  7. };
  8. // good
  9. const someNum = 123;
  10. const anotherStr = '不变的字符串';
  11. const arr = ['不', '变', '数', '组'];
  12. const anotherObj = {
  13. '不变对象': true
  14. };

字符串

•2.1 处理多行字符串,使用模板字符串,以反引号( ` )标示,可读性更强,代码更易编写。注意排版引起空格的问题,使用场景为声明HTML模板字符串

  1. // bad
  2. const tmpl = '<div class="content"> \n' +
  3. '<h1>这是换行了。</h1> \n' +
  4. '</div>';
  5. // good
  6. const tmpl = `
  7. <div class="content">
  8. <h1>这是换行了。</h1>
  9. </div>`;

•2.2 处理字符串拼接变量时,使用模板字符串

  1. // bad
  2. function sayHi(name) {
  3. return 'How are you, ' + name + '?';
  4. }
  5. // good
  6. function sayHi(name) {
  7. return `How are you, ${name}?`;
  8. }

解构

•3.1 嵌套结构的对象层数不能超过3层

  1. // bad
  2. let obj = {
  3. 'one': [
  4. {
  5. 'newTwo': [
  6. {
  7. 'three': [
  8. 'four': '太多层了,头晕晕'
  9. ]
  10. }
  11. ]
  12. }
  13. ]
  14. };
  15. // good
  16. let obj = {
  17. 'one': [
  18. 'two',
  19. {
  20. 'twoObj': '结构清晰'
  21. }
  22. ]
  23. };

•3.2 解构语句中统一不使用圆括号

  1. // bad
  2. [(a)] = [11]; // a未定义
  3. let { a: (b) } = {}; // 解析出错
  4. // good
  5. let [a, b] = [11, 22];

•3.3 对象解构

•3.3.1 若函数形参为对象时,使用对象解构赋值

  1. // bad
  2. function someFun(opt) {
  3. let opt1 = opt.opt1;
  4. let opt2 = opt.opt2;
  5. console.log(op1);
  6. }
  7. // good
  8. function someFun(opt) {
  9. let { opt1, opt2 } = opt;
  10. console.log(`$(opt1) 加上 $(opt2)`);
  11. }
  12. function someFun({ opt1, opt2 }) {
  13. console.log(opt1);
  14. }

•3.3.2 若函数有多个返回值时,使用对象解构,不使用数组解构,避免添加顺序的问题

  1. // bad
  2. function anotherFun() {
  3. const one = 1, two = 2, three = 3;
  4. return [one, two, three];
  5. }
  6. const [one, three, two] = anotherFun(); // 顺序乱了
  7. // one = 1, two = 3, three = 2
  8. // good
  9. function anotherFun() {
  10. const one = 1, two = 2, three = 3;
  11. return { one, two, three };
  12. }
  13. const { one, three, two } = anotherFun(); // 不用管顺序
  14. // one = 1, two = 2, three = 3

•3.3.3 已声明的变量不能用于解构赋值(语法错误)

  1. // 语法错误
  2. let a;
  3. { a } = { b: 123};

•3.4 数组解构

•3.4.1 交换变量的值

  1. let x = 1;
  2. let y = 2;
  3. // bad
  4. let temp;
  5. temp = x;
  6. x = y;
  7. y = temp;
  8. // good
  9. [x, y] = [y, x]; // 交换变量

•3.4.2 将数组成员赋值给变量时,使用数组解构

  1. const arr = [1, 2, 3, 4, 5];
  2. // bad
  3. const one = arr[0];
  4. const two = arr[1];
  5. // good
  6. const [one, two] = arr;

数组

•4.1 将类数组(array-like)对象与可遍历对象(如 Set , Map )转为真正数组,采用 Array.from 进行转换

  1. // bad
  2. function foo() {
  3. let args = Array.prototype.slice.call(arguments);
  4. }
  5. // good
  6. function foo() {
  7. let args = Array.from(arguments);
  8. }

•4.2 数组去重

  1. // good
  2. function deduplication(arr) {
  3. return Array.from(new Set(arr));
  4. }

•4.3 数组拷贝
- 采用数组扩展 ... 形式

  1. const items = [1, 2, 3];
  2. // bad
  3. const len = items.length;
  4. let copyTemp = [];
  5. for (let i = 0; i < len; i++) {
  6. copyTemp[i] = items[i];
  7. }
  8. // good
  9. let copyTemp = [...items];

•4.4 将一组数值转为数组

  1. // bad
  2. let arr1 = new Array(2); // [undefined x 2]
  3. let arr2 = new Array(1, 2, 3); // [1, 2, 3]
  4. // good
  5. let arr1 = Array.of(2); // [2]
  6. let arr2 = Array.of(1, 2, 3); // [1, 2, 3]

函数

•5.1 当要用函数表达式或匿名函数时,使用箭头函数(Arrow Functions),箭头函数更加简洁,并且绑定了this

  1. // bad
  2. const foo = function(x) {
  3. console.log(foo.name); // 返回'' ,函数表达式默认省略name属性
  4. };
  5. [1, 2, 3].map(function(x) {
  6. return x + 1;
  7. });
  8. var testObj = {
  9. name: 'testObj',
  10. init() {
  11. var _this = this; // 保存定义时的this引用
  12. document.addEventListener('click', function() {
  13. return _this.doSth();
  14. }, false);
  15. },
  16. doSth() {
  17. console.log(this.name);
  18. }
  19. };
  20. // good
  21. const foo = (x) => {
  22. console.log(foo.name); // 返回'foo'
  23. };
  24. [1, 2, 3].map( (x) => {
  25. return x + 1;
  26. });
  27. var testObj = {
  28. name: 'testObj',
  29. init() {
  30. // 箭头函数自动绑定定义时所在的对象
  31. document.addEventListener('click', () => this.doSth(), false);
  32. },
  33. doSth() {
  34. console.log(this.name);
  35. }
  36. };

•5.1.1 箭头函数书写约定

  1. // good
  2. const foo = x => x + x; // 注意此处会隐性return x + x
  3. const foo = (x) => {
  4. return x + x; // 若函数体有花括号语句块时须进行显性的return
  5. };
  6. [1, 2, 3].map( x => x * x);

•5.1.2 用箭头函数返回一个对象,应用括号包裹

  1. // bad
  2. let test = x => { x: x }; // 花括号会变成语句块,不表示对象
  3. // good
  4. let test = x => ({ x: x }); // 使用括号可正确return {x:x}

•5.2 立即调用函数,应该使用箭头函数

  1. // bad
  2. (function() {
  3. console.log('哈');
  4. })();
  5. // good
  6. (() => {
  7. console.log('哈');
  8. })();

•5.3 不使用 arguments , 采用rest语法 ... 代替

  1. // bad
  2. function foo() {
  3. let args = Array.prototype.slice.call(arguments);
  4. return args.join('');
  5. }
  6. // good
  7. function foo(...args) {
  8. return args.join('');
  9. }

•5.4 函数参数指定默认值

  1. // bad
  2. function foo(opts) {
  3. opts = opts || {};// 此处有将0,''等假值转换掉为默认值的副作用
  4. }
  5. // good
  6. function foo(opts = {}) {
  7. console.log('更加简洁,安全');
  8. }

•5.5 对象中的函数方法使用缩写形式,更加简洁,函数方法不要使用箭头函数,避免this指向的混乱

  1. // bad
  2. const shopObj = {
  3. des: '对象模块写法',
  4. foo: function() {
  5. console.log(this.des);
  6. }
  7. };
  8. const shopObj = {
  9. des: '对象模块写法',
  10. foo: () => {
  11. console.log(this.des); // 此处会变成undefined.des,因为指向顶层模块的this
  12. }
  13. };
  14. // good
  15. const des = '对象模块写法'; // 使用对象属性值简写方式
  16. const shopObj = {
  17. des,
  18. foo() {
  19. console.log(this.des);
  20. }
  21. };

•6.1 类名应使用帕斯卡写法( PascalCased )

  1. // good
  2. class SomeClass {
  3. }

•6.1.1 类名与花括号须保留一个空格间距,类中的方法定义时,方法名与左括号 ( 之间【不保留】空格间距,类中的方法定义时,右括号 ) 须与花括号 { 【保留】一个空格间距

  1. // bad
  2. class Foo{
  3. constructor(){
  4. // 右括号 `)` 须与花括号 `{` 仅保留一个空格间距
  5. }
  6. sayHi() {
  7. }
  8. _say () {
  9. // 方法名与左括号 `(` 之间【不保留】空格间距
  10. }
  11. }
  12. // good
  13. class Foo {
  14. constructor() {
  15. // 右括号 `)` 须与花括号 `{` 仅保留一个空格间距
  16. }
  17. sayHi() {
  18. }
  19. _say() {
  20. // 方法名与左括号 `(` 之间【不保留】空格间距
  21. }
  22. }

•6.2 定义类时,方法的顺序如下:

  1. // good
  2. class SomeClass {
  3. constructor() {
  4. // constructor
  5. }
  6. get aval() {
  7. // public getter
  8. }
  9. set aval(val) {
  10. // public setter
  11. }
  12. doSth() {
  13. // 公用方法
  14. }
  15. get _aval() {
  16. // private getter
  17. }
  18. set _aval() {
  19. // private setter
  20. }
  21. _doSth() {
  22. // 私有方法
  23. }
  24. }

•6.3 如果不是class类,不使用 new

  1. // bad
  2. function Foo() {
  3. }
  4. const foo = new Foo();
  5. // good
  6. class Foo {
  7. }
  8. const foo = new Foo();

•6.4 使用真正意思上的类Class写法,不使用 prototype 进行模拟扩展,Class更加简洁,易维护

  1. // bad
  2. function Dog(names = []) {
  3. this._names = [...names];
  4. }
  5. Dog.prototype.bark = function() {
  6. const currName = this._names[0];
  7. alert(`one one ${currName}`);
  8. }
  9. // good
  10. class Dog {
  11. constructor(names = []) {
  12. this._names = [...names];
  13. }
  14. bark() {
  15. const currName = this._names[0];
  16. alert(`one one ${currName}`);
  17. }
  18. }

•6.5 class应先定义后使用

  1. // bad
  2. let foo = new Foo();
  3. class SubFoo extends Foo {
  4. }
  5. class Foo {
  6. }
  7. // good
  8. class Foo {
  9. }
  10. let foo = new Foo();
  11. class SubFoo extends Foo {
  12. }

•6.6 this 的注意事项

  1. class Foo {
  2. constructor(x, y) {
  3. this.x = x;
  4. this.y = y;
  5. }
  6. }
  7. // bad
  8. class SubFoo extends Foo {
  9. constructor(x, y, z) {
  10. this.z = z; // 引用错误
  11. super(x, y);
  12. }
  13. }
  14. // good
  15. class SubFoo extends Foo {
  16. constructor(x, y, z) {
  17. super(x, y);
  18. this.z = z; // this 放在 super 后调用
  19. }
  20. setHeight(height) {
  21. this.height = height;
  22. return this;
  23. }
  24. }

模块

•7.1 使用 import / export 来做模块加载导出,不使用非标准模块写法

  1. // bad
  2. const colors = require('./colors');
  3. module.exports = color.lightRed;
  4. // good
  5. import { lightRed } from './colors';
  6. export default lightRed;

•7.1.1 import / export 后面采用花括号 { } 引入模块的写法时,须在花括号内左右各保留一个空格

  1. // bad
  2. import {lightRed} from './colors';
  3. import { lightRed} from './colors';
  4. // good
  5. import { lightRed } from './colors';

•7.2 应确保每个module有且只有一个默认导出模块,方便调用方使用

  1. // bad
  2. const lightRed = '#F07';
  3. export lightRed;
  4. // good
  5. const lightRed = '#F07';
  6. export default lightRed;

•7.3 import 不使用统配符 * 进行整体导入,确保模块与模块之间的关系比较清晰

  1. // bad
  2. import * as colors from './colors';
  3. // good
  4. import colors from './colors';

•7.4 不要将 import 与 export 混合在一行,分开导入与导出,让结构更清晰,可读性更强

  1. // bad
  2. export { lightRed as default } from './colors';
  3. // good
  4. import { lightRed } from './colors';
  5. export default lightRed;

•7.5 多变量要导出时应采用对象解构形式,export 置于底部,使欲导出变量更加清晰

  1. // bad
  2. export const lightRed = '#F07';
  3. export const black = '#000';
  4. export const white = '#FFF';
  5. // good
  6. const lightRed = '#F07';
  7. const black = '#000';
  8. const white = '#FFF';
  9. export default { lightRed, black, white };

React/JSX规范

1.基本规则
2.命名
3.声明
4.对齐
5.引号
6.空格
7.属性
8.括号
9.标签
10.方法
11.顺序

基本规则

  1. // bad
  2. const Listing = React.createClass({
  3. // ...
  4. render() {
  5. return <div>{this.state.hello}</div>;
  6. }
  7. });
  8. // good
  9. class Listing extends React.Component {
  10. // ...
  11. render() {
  12. return <div>{this.state.hello}</div>;
  13. }
  14. }

如果你没有使用state或refs,最好不用类,而是使用普通函数(不是箭头函数)

  1. // bad
  2. class Listing extends React.Component {
  3. render() {
  4. return <div>{this.props.hello}</div>;
  5. }
  6. }
  7. // bad (since arrow functions do not have a "name" property)
  8. const Listing = ({ hello }) => (
  9. <div>{hello}</div>
  10. );
  11. // good
  12. function Listing({ hello }) {
  13. return <div>{hello}</div>;
  14. }

命名

  1. // bad
  2. import reservationCard from './ReservationCard';
  3. // good
  4. import ReservationCard from './ReservationCard';
  5. // bad
  6. const ReservationItem = <ReservationCard />;
  7. // good
  8. const reservationItem = <ReservationCard />;
  1. // bad
  2. const Footer = require('./Footer/Footer.jsx')
  3. // bad
  4. const Footer = require('./Footer/index.jsx')
  5. // good
  6. const Footer = require('./Footer')

声明

  1. // bad
  2. export default React.createClass({
  3. displayName: 'ReservationCard',
  4. // stuff goes here
  5. });
  6. // good
  7. export default class ReservationCard extends React.Component {
  8. }

对齐

  1. // bad
  2. <Foo superLongParam="bar"
  3. anotherSuperLongParam="baz" />
  4. // good
  5. <Foo
  6. superLongParam="bar"
  7. anotherSuperLongParam="baz"
  8. />
  9. // if props fit in one line then keep it on the same line
  10. <Foo bar="bar" />
  11. // children get indented normally
  12. <Foo
  13. superLongParam="bar"
  14. anotherSuperLongParam="baz"
  15. >
  16. <Spazz />
  17. </Foo>

引号

  1. // bad
  2. <Foo bar='bar' />
  3. // good
  4. <Foo bar="bar" />
  5. // bad
  6. <Foo style={{ left: "20px" }} />
  7. // good
  8. <Foo style={{ left: '20px' }} />

空格

  1. // bad
  2. <Foo/>
  3. // very bad
  4. <Foo />
  5. // bad
  6. <Foo
  7. />
  8. // good
  9. <Foo />
  1. // bad
  2. <Foo bar={ baz } />
  3. // good
  4. <Foo bar={baz} />

属性

  1. // bad
  2. <Foo
  3. UserName="hello"
  4. phone_number={12345678}
  5. />
  6. // good
  7. <Foo
  8. userName="hello"
  9. phoneNumber={12345678}
  10. />

括号

  1. // bad
  2. render() {
  3. return <MyComponent className="long body" foo="bar">
  4. <MyChild />
  5. </MyComponent>;
  6. }
  7. // good
  8. render() {
  9. return (
  10. <MyComponent className="long body" foo="bar">
  11. <MyChild />
  12. </MyComponent>
  13. );
  14. }
  15. // good, when single line
  16. render() {
  17. const body = <div>hello</div>;
  18. return <MyComponent>{body}</MyComponent>;
  19. }

标签

  1. // bad
  2. <Foo className="stuff"></Foo>
  3. // good
  4. <Foo className="stuff" />
  1. // bad
  2. <Foo
  3. bar="bar"
  4. baz="baz" />
  5. // good
  6. <Foo
  7. bar="bar"
  8. baz="baz"
  9. />

方法

  1. function ItemList(props) {
  2. return (
  3. <ul>
  4. {props.items.map((item, index) => (
  5. <Item
  6. key={item.key}
  7. onClick={() => doSomethingWith(item.name, index)}
  8. />
  9. ))}
  10. </ul>
  11. );
  12. }
  1. // bad
  2. class extends React.Component {
  3. onClickDiv() {
  4. // do stuff
  5. }
  6. render() {
  7. return <div onClick={this.onClickDiv.bind(this)} />
  8. }
  9. }
  10. // good
  11. class extends React.Component {
  12. constructor(props) {
  13. super(props);
  14. this.onClickDiv = this.onClickDiv.bind(this);
  15. }
  16. onClickDiv() {
  17. // do stuff
  18. }
  19. render() {
  20. return <div onClick={this.onClickDiv} />
  21. }
  22. }
  1. // bad
  2. React.createClass({
  3. _onClickSubmit() {
  4. // do stuff
  5. }
  6. // other stuff
  7. });
  8. // good
  9. class extends React.Component {
  10. onClickSubmit() {
  11. // do stuff
  12. }
  13. // other stuff
  14. });

顺序

1.optional static methods
2.constructor
3.getChildContext
4.componentWillMount
5.componentDidMount
6.componentWillReceiveProps
7.shouldComponentUpdate
8.componentWillUpdate
9.componentDidUpdate
10.componentWillUnmount
11.clickHandlers or eventHandlers like onClickSubmit() or onChangeDescription()
12.getter methods for render like getSelectReason() or getFooterContent()
13.Optional render methods like renderNavigation() or renderProfilePicture()
14.render

  1. import React, { PropTypes } from 'react';
  2. const propTypes = {
  3. id: PropTypes.number.isRequired,
  4. url: PropTypes.string.isRequired,
  5. text: PropTypes.string,
  6. };
  7. const defaultProps = {
  8. text: 'Hello World',
  9. };
  10. class Link extends React.Component {
  11. static methodsAreOk() {
  12. return true;
  13. }
  14. render() {
  15. return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a>
  16. }
  17. }
  18. Link.propTypes = propTypes;
  19. Link.defaultProps = defaultProps;
  20. export default Link;

1.displayName
2.propTypes
3.contextTypes
4.childContextTypes
5.mixins
6.statics
7.defaultProps
8.getDefaultProps
9.getInitialState
10.getChildContext
11.componentWillMount
12.componentDidMount
13.componentWillReceiveProps
14.shouldComponentUpdate
15.componentWillUpdate
16.componentDidUpdate
17.componentWillUnmount
18.clickHandlers or eventHandlers like onClickSubmit() or onChangeDescription()
19.getter methods for render like getSelectReason() or getFooterContent()
20.Optional render methods like renderNavigation() or renderProfilePicture()
21.render

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注