代码格式规范化, 代码风格统一

184 阅读7分钟

样式规范

使用scss嵌套写法,scoped为组件作用域, class类名尽量语义化, 方便阅读且缩短类名长度可使用后缀衔接的方式

如:

<style lang="scss" scoped>
    /* 这是注释 */
    .pvc-test-tree {
        .test-tree-title {
            .title-icon {
                color: '#ccc';
            }
        }
        .test-tree-content {
            .content-table {}
        }
    }
</style>

代码格式化

样式书写分紧凑格式和展开格式, 统一用展开格式书写样式

/* 不推荐 */
.jdc { display: block;width:50px;}
/* 推荐 */
.jdc {
    display: block;
    width: 50px;
}

代码大小写

样式选择器, 属性名, 属性值全部小写, 属性字符串允许使用大小写

/* 推荐 */
.jdb {
    display: block;
}
/* 不推荐 */
.JDC {
    DISPLAY: BLOCK;
}

选择器

  • 尽量少用通配符选择器 *
  • 不使用 ID 选择器
  • 不使用无具体语义定义的标签选择器
/* 不推荐 */
* {}
#jdc {}
.jdc div {}
/* 推荐 */
.jdc {}
.jdc li {}
.jdc li p {}

分号

每个属性声明末尾都要加分号 ;

.jdc {
    width: 100%;
    height: 100%;
}

代码易读性

为单个css 选择器或新申明开启新行

.jdc,
    .jdc_logo,
        .jdc_hd {
            color: '#ffo';
        }
.nav {
    color: '#fff';
}

属性值引号

css属性值需要用引号时, 统一使用单引号

.jdc {
    font-family: 'Hiragino Sans GB';
}

注释规范

注释以字符 /* 开始, 以字符 */ 结束

/* 注释 */
.jdc {
    display: block;
}

js 书写规范

空格

if-else、for、function...... 与 () {} 之间保留空格

箭头函数 () => {} 保留空格

函数参数之间保留空格

< > = + - * % ?&& || 号两边保留空格

// if-else
if (condition) {
​
} else {
​
}
​
// for
for (let index = 0; index < array.length; index++) {
    
}
// function
function name(params) {
​
}
// class
class Event {
    constructor() {
        
    }
}
// 箭头函数
const init = () => {
    
}
// 三元表达式
const value = num === 0 ? 1 : 2
// 赋值
const name = 18
// 判断大小
if (num >= 20) return
// 计算
const year = (2000 + 23) * 1
// 对象
const info = {name: 'tom', age: 19}

大括号风格

if (foo) {
    bar();
} else {
    baz();
}

链式赋值

// 禁止
const a = b = c = 1;
// 推荐
const a = 1;
const b = 1;
const c = 1;

变量声明

禁止在一个声明中声明多个变量

// 禁止
const a, b, c;
// 推荐
const a;
const b;
const c;

使用const let 关键字进行变量声明并分组, 禁止不写关键字, 直接暴露在全局上下文, 可能导致与现有变量冲突

const b;
const d;
let a;
let c;
let e;

函数声明

不要在(if, while 等) 中声明函数

// 错误
if (isUse) {
    function test () {
        // do something
    }
}
// 正确
let test;
if (isUse) {
    test = () => {
        // do something
    }
}

不要将参数命名为arguments, 会导致该参数的优先级高于每个函数作用域内原先存在的arguments 对象

// 错误
function foo (name,options,arguments) {
    // ...
}
// 正确
function foor (name,options,args) {
​
}

不要使用 arguments, 只是一个类数组, 要使用展开运算符 ... ,才是一个真正的数组

// 错误
function test () {
    const args = Array.prototype.slice.call(arguments);
    return args.join('')
}
// 正确
function test (...args) {
    return args.join('')
}

使用函数默认参数, 不要修改函数参数值

// 错误
function handleThings (opts) {
    opts = opts || {};
    // ...
}
// 错误
function handleThings (opts) {
    if (opts === void 0) {
        opts = {}
    }
    // ...
}
// 正确
function handleThings (opts = {}) {
    // ...
}

类&构造函数

使用 class, 避免直接操作 prototype

// 不推荐
function Queue (contents = []) {
    this._queue = [...contents];
}
Queue.prototype.pop = function () {
    const value = this._queue[0];
    this._queue.splice(0,1);
    return value
}
​
// 推荐
class Queue {
    constructor (contents = []) {
        this._queue = [...contents];
    }
    private pop () {
        const value = this._queue[0];
        this._queue.splice(0,1);
        return value
    }
}

使用 extends 来实现继承

原因: 这是一个不会破坏 instanceof 的内建实现原型式继承的方式

// 错误
const inherits = require('inherits');
function PeekableQueue(contents) {
    Queue.apply(this,contents);
}
inherits(PeekableQueue,Queue);
PeekableQueue.prototype.peek = function () {
    return this.queue[0]
}
​
// 正确
class PeekableQueue extends Queue {
    public peek () {
        return this.queue[0]
    }
}

构造函数首字母大写

const footItem = new Foo();

类和函数的命名

函数采用小驼峰命名, 类采用大驼峰命名, 类的含义尽可能为名词, 函数为动词

const replayer = new Replayer();
function transTo() {}

类的函数成员和变量成员

  • 明确成员的作用域, 必须在成员前标识成员的作用域, private, protect和public
  • 变量成员命名采用 '_' 开头
class MyClass {
    private _test;
    public getText() {
​
    }
}

函数参数个数限制

函数参数个数限定在4个以内, 包含4, 函数参数过长容易漏, 也无法很好扩展

// 不推荐
function trans(num1, num2, isChange, isRevert, isCount) {
​
}
//推荐
function trans(num1, num2, options: {isChange, isRevert, isCount}) {
​
}

注释规范

单行注释:

独占一行, 注释内容和注释符之间需要有一个空格

// 将文本转换成base64
let base64 = trans2Base64(text);
多行注释:

非类和函数避免使用 /**/ 这样的多行注释, 有多行注释内容时, 使用多个单行注释

// 将文本转换成base64
// 目的是为了转base64
let base64 = trans2Base64(text);
类注释:

类必须添加注释, 并符合 jsdoc 导出规范

/**
 * Book类,代表一个书本.
 * @constructor
 * @param {string} title - 书本的标题.
 * @param {string} author - 书本的作者.
 */
class BookClass {
​ constructor(title, author) {
  }
}
函数/方法注释:

函数/方法必须添加注释, 并符合 jsdoc 导出规范

必须包含类的说明; 有参数和返回值时, 必须有注释标志; 参数和返回值必须包含类型信息和说明; 当函数是内部函数, 外部不可以访问时,可以使用 @inner 来标识; 示范:

/**
 * 计算总价
 * @param {number} price 商品价格
 * @returns {number} 加税后的总价
 */
function calculateTotal(price) {
    return price * 1.08; // 1.08 是税率
}
文件注释:

文件注释用于告诉不熟悉这段代码的读者这个文件中包含哪些东西。文件注释要标明作者、文件版本、创建/修改时间、重大版本修改记录; 示范

/**
 * 文件描述
 * @Author: nobady
 * @Date: 2022-04-24 17:14
 * @Last Modified by: somebody
 * @Last Modified time: 2022-04-24 17:14
 */

版本号规范

  1. 软件版本阶段说明     Alpha版: 此版本表示该软件在此阶段主要是以实现软件功能为主,通常只在软件开发者内部交流,一般而言,该版本软件的Bug较多,需要继续修改。

    Beta版: 该版本相对于α版已有了很大的改进,消除了严重的错误,但还是存在着一些缺陷,需要经过多次测试来进一步消除,此版本主要的修改对像是软件的UI。

    RC版: 该版本已经相当成熟了,基本上不存在导致错误的BUG,与即将发行的正式版相差无几。

    Release版: 该版本意味“最终版本”,在前面版本的一系列测试版之后,终归会有一个正式版本,是最终交付用户使用的一个版本。该版本有时也称为标准版。一般情况下,Release 不会以单词形式出现在软件封面上,取而代之的是符号(R)。

  1. 版本命名规范     软件版本号由四部分组成:

    第一个1为主版本号

    第二个1为子版本号

    第三个1为阶段版本号

    第四部分为日期版本号加希腊字母版本号

    希腊字母版本号共有5种,分别为:base、alpha、beta、RC、release。例如:1.1.1.051021_beta

    常规:完全的版本号定义,分三项::<主版本号>.<次版本号>.<修订版本号>,如 1.0.0

  1. 版本号定修改规则     主版本号(1):当功能模块有较大的变动,比如增加多个模块或者整体架构发生变化。此版本号由项目决定是否修改。

    子版本号(1):当功能有一定的增加或变化,比如增加了对权限控制、增加自定义视图等功能。此版本号由项目决定是否修改。

    阶段版本号(1):一般是 Bug 修复或是一些小的变动,要经常发布修订版,时间间隔不限,修复一个严重的bug即可发布一个修订版。此版本号由项目经理决定是否修改。

    日期版本号(051021): 用于记录修改项目的当前日期,每天对项目的修改都需要更改日期版本号。此版本号由开发人员决定是否修改。

    希腊字母版本号(beta): 此版本号用于标注当前版本的软件处于哪个开发阶段,当软件进入到另一个阶段时需要修改此版本号。此版本号由项目决定是否修改。