# 开发规范

# Git 规范

# 分支命名

  • master 记录上线集成到设备版本的迭代啊
  • dev 开发分支
  • feature-* 新功能分支,根据主要功能进行命名
  • bugfix bug 修复分支,根据测试反馈的 bug,从 dev 分支创建,完成后合并到 dev 分支
  • hotfix 紧急 bug 修复分支,紧急情况下是,从 master 分支创建,完成后合并到 dev 和 master 分支

# 提交规范

  • feature: 新功能
  • fix: 修复问题
  • style: 代码格式修改
  • docs: 文档修改
  • refactor: 代码重构
  • test: 增加测试,修改测试用例
  • chore: 构建或辅助工具变动

# 一些细节

  • git push 代码前,每次都要复查,改动和新增的代码
  • git push 代码前,可以使用git commit --amend来合并 commit,合并完成后提交在 push 到在线仓库
  • git rebase -i 指令可以规整 commit 历史记录,建议仅在开发个人项目时使用

# JS 规范

# 变量

命名方式:小驼峰,使用前缀表示其语义

// bad
let count = 0;
// good
let totalCount = 10;

# 常量

命名方式:全部大写,使用下划线分隔

const serverErrorCode = {};

const SERVER_ERROR_CODE = {};

# 函数/方法

命名方式: 动词 + 小驼峰

// bad
function dialogOpen() {}
// good
function openDialog() {}

# 函数/事件

命名方式: on + 小驼峰

// bad
function dialogClosed() {}
// good
function onDialogClosed() {}

# 函数/类

命名方式:大驼峰

// bad
function person() {}
class person {}
// good
function Person() {}
class Person {}

# 减少嵌套

确定条件不允许时,尽早返回或者 continue

# 标记值自解释

// bad
// 1 read 2 edit
Graph.mode = 1;

// good
const GRAPH_MODE = {
  READ: 1,
  EDIT: 2
};
Node.shape = GRAPH_MODE.READ;

# 变量名自解释

逻辑复杂时,建议使用变量名自解释,而不是晦涩难懂的简写。

// bad
function(value) {
    return !helpers.req(value) || this.entity.entVocabularyEntries.filter(item => item.vocabularyEntryName === value).length < 2
}

// good
function(value) {
    let entVocabularyList = this.entity.entVocabularyEntries
    let repeatCount = entVocabularyList.filter(item => item.vocabularyEntryName === value).length
    return !helpers.req(value) || repeatCount < 2
}

# 函数名自解释

函数模块封装

// bad
for (let i = 0; i < blocks.length; i++) {
  for (let j = 0; j < blocks.length; i++) {
    if (i != j) {
      let rect1 = blocks[i];
      let rect2 = blocks[j];
      if (
        rect1.x < rect2.x + rect2.width &&
        rect1.x + rect1.width > rect2.x &&
        rect1.y < rect2.y + rect2.height &&
        rect1.height + rect1.y > rect2.y
      ) {
        // dosomething
      }
    }
  }
}

// good

function isHit(rect1, rect2) {
  return (
    rect1.x < rect2.x + rect2.width &&
    rect1.x + rect1.width > rect2.x &&
    rect1.y < rect2.y + rect2.height &&
    rect1.height + rect1.y > rect2.y
  );
}

for (let i = 0; i < blocks.length; i++) {
  for (let j = 0; j < blocks.length; i++) {
    if (i != j) {
      let rect1 = blocks[i];
      let rect2 = blocks[j];
      if (isHit(rect1, rect2)) {
        // dosomething
      }
    }
  }
}

# CSS 规范

# 分号

每个属性声明后面都要加分号

# 命名

命名方式:全部小写,BEM 命名

# 顺序

书写原则:整体到局部,由外到内

/* 示例 */
.element {
  display: flex;
  flex-direction: row;
  justify-content: center;
  width: 100%;
  height: 100%;
  margin: 10px;
  padding: 10px;
  border: 1px solid #409eff;
  border-radius: 5px;
  text-align: left;
  font-size: 16px;
  font-family: "微软雅黑";
  color: #333;
}

# Vue 规范

# 组件选项顺序

export default {
  name: "",
  /*1. Vue扩展 */
  extends: "", // extends和mixins都扩展逻辑,需要重点放前面
  mixins: [],
  components: {},
  /* 2. Vue数据 */
  props: {},
  model: { prop: "", event: "" }, // model 会使用到 props
  data() {
    return {};
  },
  computed: {},
  watch: {}, // watch 监控的是 props 和 data,有必要时监控computed
  /* 3. Vue资源 */
  filters: {},
  directives: {},
  /* 4. Vue生命周期 */
  created() {},
  mounted() {},
  destroyed() {},
  /* 5. Vue方法 */
  methods: {} // all the methods should be put here in the last
};

# 组件属性顺序

类名-> 属性 -> 指令 -> 参数 -> 事件

<template>
  <u-select
    class="select"
    size="mini"
    v-model="row.variableId"
    :list="variableList"
    @select="searchEntity($event, row)"
    @blur="searchEntity($event, row)"
  ></u-select>
</template>

# 组件设计风格

1.Element 元素 统一使用 EL 后缀

// ✗ bad
const elem = this.$el;
const canvas = this.$refs.canvasRef;
// ✓ good
const el = this.$el;
const canvasEL = this.$refs.canvasRef;

2.事件使用 on 前缀

// ✗ bad
{
    methods: {
        input() {
            // ...
        },
        handleValidate() {
            // ...
        },
    },
}
// ✓ good
{
    methods: {
        onInput() {
            // ...
        },
        onValidate() {
            // ...
        },
    },
}

3.动作使用动词前缀

// ✗ bad
{
    methods: {
        userList() {
            // ...
        }
    }
}
// ✓ good
{
    methods: {
        getUserList() {
            // ...
        }
    }
}

# 工程约定

# Prettier 配置

// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
  printWidth: 120,
  tabWidth: 2,
  useTabs: false,
  semi: true,
  singleQuote: false,
  trailingComma: "none",
  bracketSpacing: true,
  arrowParens: "always",
  htmlWhitespaceSensitivity: "ignore"
};

# Husky 配置

npm install husky -D
# 要求npm版本在8以上
npm set-script prepare "husky install"
npm run prepare
husky add .husky/pre-commit "npm run format"
git add .husky/pre-commit

# 参考资料

AI 前端 JS 规范 (opens new window)
AI 前端 Git 规范 (opens new window)
Commit message 和 Change log 编写指南 (opens new window)
教你使用最新版 husky 让代码更优雅规范 (opens new window)
为什么 husky 放弃了传统的 JS 配置 (opens new window)