概述
标准代码是项目质量的保证。 本代码规范从TypeScript、JavaScript、CSS、Vue等几个方面为日常开发中的代码编译提供了规范性的指导和建议,可以有效防止代码级的缺陷和错误; 您还可以使用此规范来在代码审查中提出有关不符合规范的代码的问题。
优先级声明 A:必需
这是特殊情况下必须遵循的规范。 一般来说,此规范将帮助您防止错误。
乙:强烈推荐
大多数被广泛使用的规则可以提高代码可读性和开发体验typescript日期函数,但即使违反也不会导致错误。
C:谨慎使用
使用标准是有风险的。 这个标准可能会解决一些更复杂的问题,但也会带来潜在的风险。 当你编译这种代码时,你需要仔细考虑可能出现的问题。
姓名
标准化文件和目录的命名。
(一个专案
全部大写并用逗号分隔多个短语。
// bad
cisdiPlatform
CisdiPlatform
// good
cisdi_platform
(一)目录、文件夹
参考项目名称,当存在复数结构时,使用复数命名法。
(一)JavaScript文件
以项目命名。
(一)css、less、scss 文件
以项目命名。
(一)html文件
参考项目命名。
(一)vue文件
使用 PascalCase 命名约定。
// bad
headerTitle.vue
header_title.vue
// good
HeaderTitle.vue
脚本语言
javascript代码规范详细解释。
(A) 使用let、const,不要使用var
// bad
var bar = 1;
var PI = 3.14;
// good
let bar = 1;
const PI = 3.14;
参考:
(一)变量命名
// bad
let table_data;
// good
let tableData;
// bad
const one_day = 24 * 3600 * 1000;
const oneDay = 24 * 3600 * 1000;
// good
const ONE_DAY = 24 * 3600 * 1000;
// bad
let shijian;
// good
let time;
(A) 链表、对象格式
// bad
let foo = { "a": 1 };
let bar = { a: 1, b: 2 };
// good
let foo = {
a: 1,
'prop-name': 'name'
};
(A)浅复制对象和数组时,更推荐使用扩展运算符
// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 });
delete copy.a;
// 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 }
// rest 解构运算符
const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i += 1) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
(A) 关键字后面必须有大括号
下面的关键字后面必须跟大括号(虽然代码块的内容只有一行):if、else、for、while、do、switch、try、catch、finally、with。
const condition = Math.random() > 0.5;
// bad
if (condition) return;
// good
if (condition) {
return;
}
(A) 未定义的使用
严禁直接使用undefined来判断变量; 使用 typeof 和字符串 'undefined' 来判断变量。
let name;
// bad
console.log(name === undefined);
// good
console.log(typeof name === 'undefined');
(A)换入
使用 for-in 时,必须有一个 hasOwnProperty 判别。
let foo = {
a: 1,
b: 2
};
foo.__proto__.c = 3;
// bad
for (let item in foo) {
console.log(item);
}
// 1,2,3
// good
for (let item in foo) {
if (foo.hasOwnProperty(item)) {
console.log(item);
}
}
// 1,2
(A)函数参数不能超过3个
如果超过3个typescript日期函数,则使用对象的方法来传递。
// bad
const foo = (a, b, c, d) => {
console.log(a, b, c, d);
};
// good
const foo = args => {
const { a, b, c, d } = args;
console.log(a, b, c, d);
};
(一)严禁全局变量,禁止全局变量被污染
// bad
bar = 1;
window.bar = 1;
// good
const bar = 1;
(A) 使用类代替函数
// bad
function User(name) {
this.name = name;
}
User.prototype.hello = function() {
console.log(this.name);
};
// good
class User {
constructor(name) {
this.name = name;
}
hello() {
console.log(this.name);
}
}
(A) 使用Promise代替bounce函数
// bad
require('request').get('api_url', function(err, response) {
if (err) {
console.error(err);
} else {
require('fs').writeFile('article.html', response.body, function(err) {
if (err) {
console.error(err);
} else {
console.log('File written');
}
});
}
});
// good
const request = require('request-promise').get('api_url');
request.then(response => {
console.log(response);
});
(A) 注册和卸载的代码必须同时存在
// bad
mounted() {
window.addEventListener('resize', resizeHandler);
}
// good
mounted() {
window.addEventListener('resize', resizeHandler);
},
beforeDestroy() {
window.removeEventListener('resize', resizeHandler);
}
(A) 防止无意义的条件判断
使用|| 和 && 运算符优先。
// bad
function createMicrobrewery(name) {
let breweryName;
if (name) {
breweryName = name;
} else {
breweryName = 'Hipster Brew Co.';
}
}
// good
function createMicrobrewery(name) {
let breweryName = name || 'Hipster Brew Co.';
}
(A) 使用模板字符串
这可以防止出现诸如增加代码可读性以及直接连接字符串导致的错误倾向等问题。
const date = '2011-01-01';
const time = '12:00';
// bad
const fullTime = date + ' ' + time;
// good
const fullTime = `${date} ${time}`;
(A) 无效或过时的代码、注释或文件不得出现在最终评审中
对代码的所有更改都应该可以通过 git 进行跟踪,因此无需在最新的代码库中保留无效的、过时的代码、注释等。
(A) 使用 === 和 !== 代替 == 和 != (B) 变量命名风格 (B) 函数参数使用默认值
// bad
function writeForumComment(subject, body) {
subject = subject || 'No Subject';
body = body || 'No text';
}
// good
function writeForumComment(subject = 'No subject', body = 'No text') {
// todo
}
(B) 使用 async/await 函数
// bad
const request = require('request-promise').get('api_url');
request.then(response => {
console.log(response);
});
// good
async function getCleanCodeArticle() {
try {
let request = await require('request-promise');
let response = await request.get('api_url');
let fileHandle = await require('fs-promise');
await fileHandle.writeFile('article.html', response);
console.log('File written');
} catch (err) {
console.log(err);
}
}
(B) 更喜欢使用 const
对于明确且不会改变的值,最好使用const进行变量声明,以防止值被意外改变。
// bad
let PI = 3.14;
// good
const PI = 3.14;
(B) 单行代码宽度不能超过160个字符
单行代码太长会增加代码的可读性,需要限制单行代码的宽度。
(二) 注释
以下情况建议使用注释来解释代码:
// bad
function hashIt(data) {
// The hash
let hash = 0; // Length of string
let length = data.length; // Loop through every character in data
for (let i = 0; i < length; i++) {
// Get character code.
let char = data.charCodeAt(i); // Make the hash
hash = (hash << 5) - hash + char; // Convert to 32-bit integer
hash = hash & hash;
}
}
// good
function hashIt(data) {
let hash = 0;
let length = data.length;
for (let i = 0; i < length; i++) {
let char = data.charCodeAt(i);
hash = (hash << 5) - hash + char; // Convert to 32-bit integer
hash = hash & hash;
}
}
(B) 多行注释格式
至少三行,* 后跟一个空格。
/*
* one space after '*'
*/
const num = 1;
(二)以按需加载的方式使用第三方库
尽量减少第三方库的引用大小,保证打包文件规格在可控范围内。
大多数主要的第三方库都提供开箱即用的按需加载机制。
// bad
import _ from 'lodash';
// good
import pick from 'lodash/pick';
(B) 使用第三方库处理日期
数据处理是一个极其常见的需求,并且有很多成熟的工具。 自己发明轮子会带来不必要的风险。
// bad
function format(date) {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
return `${year}-${month}-${day}`;
}
// good
import dayjs from 'dayjs';
dayjs().format('YYYY-MM-DD');
(B) 对象的属性总是缩写的
更新
属性缩写使代码更加简洁。 当缩写属性和非缩写属性同时存在时,防止缩写属性和非缩写属性混合排列。
const name = 'sam';
const age = 12;
// bad
const person = {
name: name
};
// good
const person = {
name
};
// bad
const person = {
name,
sex: 'male',
age,
country: 'china'
};
// good
const person = {
name,
age,
sex: 'male',
country: 'china'
};
(B) 包复杂判断条件
// bad
if (fsm.state === 'fetching' && isEmpty(listNode)) {
// / ...
}
// good
function shouldShowSpinner(fsm, listNode) {
return fsm.state === 'fetching' && isEmpty(listNode);
}
if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
// ...
}
(B) 仅在必要时参考
// bad
mounted() {
const that = this;
setTimeout(() => {
that.doSomething();
}, 1000);
}
// good
mounted() {
setTimeout(() => {
this.doSomething();
}, 1000);
}
(C) 防止“负面情况”判定
// bad
function isDOMNodeNotPresent(node) {
// ...
}
if (!isDOMNodeNotPresent(node)) {
// ...
}
// good
function isDOMNodePresent(node) {
// ...
}
if (isDOMNodePresent(node)) {
// ...
}
(C) setInterval的使用
谨慎使用setInterval,尤其是反弹期间有网络请求时。 当网络状况较差时,请求堆积的风险会大大降低,并且会影响后续的数据显示和处理。
// bad
setInterval(request, 1000);
// good
function longRequest() {
request().then(result => {
setTimeout(longRequest, 1000);
});
}
TypeScript (A) 命名
// Bad
const Foo = 1
// Good
const foo = 1
// Bad
const UserList:string[] = []
// Good
const userList:string[] = []
// Bad
function Foo() {}
// Good
function foo() {}
// Bad
class Foo {
Bar: number;
Baz(): number {}
}
// Good
class Foo {
bar: number;
baz(): number {}
}
接口
接口本身使用 PascalCase 方式命名,不要在接口名前加I。接口成员使用 camelCase 方式命名。
// Bad
interface IFoo {
Bar: number;
Baz(): number;
}
// Good
interface Foo {
bar: number;
baz(): number;
}
// Bad
enum status {}
// Good
enum Status {}
// Bad
enum Status {
success = 'success'
}
// Good
enum Status {
Success = 'success'
}