代码规范

# 项目结构型命名规范

除特殊说明外,文件,文件夹命名遵循小驼峰命名法

# API命名规范

以所属业务为一个文件进行管理,一端对应一个文件夹,一个一级菜单/一类模块对应一个Api文件,可酌情拆分

# 组件命名规范

一个组件对应一个文件夹,该文件夹结构为

FaceRc 		   				# 人脸组件  
    ├── components 		# 组件的实现  
      └── index.js/index.jsx/index.ts/index.tsx/index.vue等等 		# 组件的具体实现  
    ├── styles 				# 组件的样式  
      └── index.css/index.scss/index.less等等  # 样式/样式导出  
    └── index.js/index.ts等等  # 导出组件  

# 指令命名规范

以v-为前缀

v-click-outside               # 某指令
	├── others                  # 自行扩展
	└── index.ts                # 指令实现(记得将指令名去除v-前缀)

# 路由命名规范

路由中的组件引入尽量为 component: () => import(某组件路径)

# 状态命名规范

状态的设置,更新,删除务必以Set,Update,Del为前缀

采用action提交mutation的方式

// 以设置token为例

// es6版
  state: {
  token: ''
},
mutations: {
  SET_TOKEN (state, token) {
    state.token = token
  }
},
actions: {
  SetToken (context, token) {
    context.commit('SET_TOKEN', token)
  }
}

// typescript版
public token = '';

@Mutation
public SET_TOKEN(token: string) {
  this.token = token
}

@Action({ commit: 'SET_TOKEN' })
public SetToken(token: string) {
  return token
}

# 页面内命名规范

# 普通变量命名规范

# 命名规范 :

变量命名需语义化,出现魔术数字时需加注释(解释该数的作用)

变量名含有复数含义时需加s,let names = ['张三', '李四']

::: tip 什么是魔术数字?

缺乏解释或命名的独特数值,常常在程序中出现多次。

// bad
let num = 10

// good
// 标签最大数量
let maxTagsNum = 10

:::

# 常量

命名方法 : 全部大写
命名规范 : 使用大写字母和下划线来组合命名,下划线用以分割单词。

const MAX_COUNT = 10
const URL = 'https://www.baidu.com/'

# 组件命名规范

官方文档推荐及使用遵循规则:

声明规范:PascalCase (单词首字母大写命名)

使用规范:kebab-case (短横线分隔命名)

组件名应该始终是多个单词的,根组件 App 除外
有意义的名词、简短、具有可读性
命名遵循 PascalCase 约定
公用组件以 Pc(破产条线缩写简称) 开头,如(PcDialog)
页面内部组件以组件模块名简写为开头,Item 为结尾,如(StaffBenchToChargeItem,StaffBenchAppNotArrItem)
使用遵循 kebab-case 约定
在页面中使用组件需要前后闭合,并以短线分隔,如(`
导入及注册组件时,遵循 PascalCase 约定
同时还需要注意:必须符合自定义元素规范: 切勿使用保留字。

# METHOD 方法命名命名规范

驼峰式(camelCase)命名,统一使用动词或者动词+名词形式, click事件的回调函数需额外添加handle前缀
//bad go、nextPage、show、open、login

// good jumpPage、openCarInfoDialog、handleGoLogin

请求数据方法,以 data 结尾 //bad takeData、confirmData、getList、postForm

// good getListData、postFormData

init、refresh 单词除外
尽量使用常用单词开头(set、get、go、can、has、is)
附: 函数方法常用的动词:

前缀 含义 前缀 含义
get 获取 set 设置
add 增加 remove 删除
create 创建 destory 移除
start 启动 stop 停止
open 打开 close 关闭
read 读取 write 写入
load 载入 save 保存
begin 开始 end 结束
backup 备份 restore 恢复
import 导入 export 导出
split 分割 merge 合并
inject 注入 extract 提取
attach 附着 detach 脱离
bind 绑定 separate 分离
view 查看 browse 浏览
edit 编辑 modify 修改
select 选取 mark 标记
copy 复制 paste 粘贴
undo 撤销 redo 重做
insert 插入 delete 移除
add 加入 append 添加
clean 清理 clear 清除
index 索引 sort 排序
find 查找 search 搜索
increase 增加 decrease 减少
play 播放 pause 暂停
launch 启动 run 运行
compile 编译 execute 执行
debug 调试 trace 跟踪
observe 观察 listen 监听
build 构建 publish 发布
input 输入 output 输出
encode 编码 decode 解码
encrypt 加密 decrypt 解密
compress 压缩 decompress 解压缩
pack 打包 unpack 解包
parse 解析 emit 生成
connect 连接 disconnect 断开
send 发送 receive 接收
download 下载 upload 上传
refresh 刷新 synchronize 同步
update 更新 revert 复原
lock 锁定 unlock 解锁
checkOut 签出 checkIn 签入
submit 提交 commit 交付
push pull
expand 展开 collapse 折叠
begin 起始 end 结束
start 开始 finish 完成
enter 进入 exit 退出
abort 放弃 quit v离开

# VIEWS 下的文件命名

只有一个文件的情况下不会出现文件夹,而是直接放在 views 目录下面,如 index.vue
尽量是名词,且使用驼峰命名法
开头的单词就是所属模块名字(workbenchIndex、workbenchList、workbenchEdit)
名字至少两个单词(good: workbenchIndex)(bad:workbench)
PROPS 命名
在声明 prop 的时候,其命名应该始终使用驼峰命名法,而在模板中使用应该用短横线分割命名法

<!-- bad -->
<script>
props: {
  'greeting-text': String
}
</script>

<welcome-message greetingText="hi"></welcome-message>

<!-- good -->
<script>
props: {
  greetingText: String
}
</script>

<welcome-message greeting-text="hi"></welcome-message>

# 例外情况

作用域不大临时变量可以简写,比如:str,num,bol,obj,fun,arr。 循环变量可以简写,比如:i,j,k 等。

# vue文件结构化规范

详细版请查看vue风格指南

# VUE 文件基本结构

 <template>
    <div>
      <!--必须在div中编写页面-->
    </div>
  </template>
  <script>
    export default {
      components : {
      },
      data () {
        return {
        }
      },
      mounted() {
      },
      methods: {
      }
   }
  </script>
  <!--声明语言,并且添加scoped-->
  <style lang="scss" scoped>
  </style>

# 多个特性的元素规范

多个特性的元素应该分多行撰写,每个特性一行。(增强更易读)

<!-- bad -->
<img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
<my-component foo="a" bar="b" baz="c"></my-component>

<!-- good -->
<img
  src="https://vuejs.org/images/logo.png"
  alt="Vue Logo"
>
<my-component
  foo="a"
  bar="b"
  baz="c"
>
</my-component>

元素特性的顺序 原生属性放前面,指令放后面

如下所示:

  • class
  • id,ref
  • name
  • data-*
  • src, for, type, href,value,max-length,max,min,pattern
  • title, alt,placeholder
  • aria-*, role
  • required,readonly,disabled
  • is
  • v-for
  • key
  • v-if
  • v-else-if
  • v-else
  • v-show
  • v-cloak
  • v-pre
  • v-once
  • v-model
  • v-bind,:
  • v-on,@
  • v-html
  • v-text

组件选项顺序 如下所示:

  • name
  • components
  • mixins
  • props
  • data
  • computed
  • watch
  • created
  • mounted
  • beforeDestroy
  • methods
  • filter

# 注释规范

代码注释在一个项目的后期维护中显的尤为重要,所以我们要为每一个被复用的组件编写组件使用说明,为组件中每一个方法编写方法说明

强制添加注释或写README.MD
除特别说明外,请遵循以下规范

# 公共组件使用说明

注释块必须以/(至少两个星号)开头/
单行注释使用//

# 单行注释

注释单独一行,不要在代码后的同一行内加注释。例如:

  // bad

  let name =”abc”; // 姓名    

  // good

  // 姓名
  let name = “abc”;     

# 多行注释

组件使用说明,和调用说明


      /**
      * 组件名称
      * @module 组件存放位置
      * @desc 组件描述
      * @author 组件作者
      * @date 2017年12月05日17:22:43
      * @param {Object} [title]    - 参数说明
      * @param {String} [columns] - 参数说明
      * @example 调用示例
      *  <hbTable :title="title" :columns="columns" :tableData="tableData"></hbTable>
      **/

# 编码规范

项目内置ESLint校验,请在VScode编辑器不报格式错误的情况下提交代码

# 源码风格

使用 ES6 风格编码

定义变量使用 let ,定义常量使用 const 静态字符串一律使用单引号或反引号,动态字符串使用反引号

 // bad
  const a = 'foobar'
  const b = 'foo' + a + 'bar'

  // acceptable
  const c = `foobar`

  // good
  const a = 'foobar'
  const b = `foo${a}bar`
  const c = 'foobar'

# 解构赋值

数组成员对变量赋值时,优先使用解构赋值

// 数组解构赋值
  const arr = [1, 2, 3, 4]
  // bad
  const first = arr[0]
  const second = arr[1]

  // good
  const [first, second] = arr

函数的参数如果是对象的成员,优先使用解构赋值

// 对象解构赋值
  // bad
  function getFullName(user) {
    const firstName = user.firstName
    const lastName = user.lastName
  }

  // good
  function getFullName(obj) {
    const { firstName, lastName } = obj
  }

  // best
  function getFullName({ firstName, lastName }) {}

# 拷贝数组

使用扩展运算符(...)拷贝数组。

 const items = [1, 2, 3, 4, 5]

  // bad
  const itemsCopy = items

  // good
  const itemsCopy = [...items]

# 箭头函数

需要使用函数表达式的场合,尽量用箭头函数代替

// bad
  const self = this;
  const boundMethod = function(...params) {
    return method.apply(self, params);
  }

  // acceptable
  const boundMethod = method.bind(this);

  // best
  const boundMethod = (...params) => method.apply(this, params);

# 模块

如果模块只有一个输出值,就使用 export default,如果模块有多个输出值,使用 export,视情况而定可混用export default与export 接口导出强制使用export,便于按需引入

  // bad
  import * as myObject from './importModule'

  // good
  import myObject from './importModule'

如果模块默认输出一个函数,函数名的首字母应该小写。

  function makeStyleGuide() {
  }

  export default makeStyleGuide;

如果模块默认输出一个对象,对象名的首字母应该大写。

  const StyleGuide = {
    es6: {
    }
  };

  export default StyleGuide;

# 指令规范

指令有缩写一律采用缩写形式

  // bad
  v-bind:class="{'show-left':true}"
  v-on:click="getListData"

  // good
  :class="{'show-left':true}"
  @click="getListData"

v-for 循环必须加上 key 属性,在整个 for 循环中 key 需要唯一

  <!-- good -->
  <ul>
    <li v-for="todo in todos" :key="todo.id">
      {{ todo.text }}
    </li>
  </ul>

  <!-- bad -->
  <ul>
    <li v-for="todo in todos">
      {{ todo.text }}
    </li>
  </ul>

避免 v-if 和 v-for 同时用在一个元素上(性能问题)

以下为两种解决方案:

将数据替换为一个计算属性,让其返回过滤后的列表

 <!-- bad -->
  <ul>
    <li v-for="user in users" v-if="user.isActive" :key="user.id">
      {{ user.name }}
    </li>
  </ul>

  <!-- good -->
  <ul>
    <li v-for="user in activeUsers" :key="user.id">
      {{ user.name }}
    </li>
  </ul>

  <script>
  computed: {
    activeUsers: function () {
      return this.users.filter(function (user) {
        return user.isActive
      })
    }
  }
  </script>

将 v-if 移动至容器元素上 (比如 ul, ol)

<!-- bad -->
  <ul>
    <li v-for="user in users" v-if="shouldShowUsers" :key="user.id">
      {{ user.name }}
    </li>
  </ul>

  <!-- good -->
  <ul v-if="shouldShowUsers">
    <li v-for="user in users" :key="user.id">
      {{ user.name }}
    </li>
  </ul>

# PROPS 规范

Props 定义应该尽量详细

// bad 这样做只有开发原型系统时可以接受
props: ['status']

// good
props: {
  status: {
    type: String,
    required: true,
    validator: function (value) {
      return [
        'syncing',
        'synced',
        'version-conflict',
        'error'
      ].indexOf(value) !== -1
    }
  }
}

# CSS 规范

# 通用规范

统一使用"-"连字符 省略值为 0 时的单位

 // bad
  padding-bottom: 0px;
  margin: 0em;

 // good
  padding-bottom: 0;
  margin: 0;

如果 css 可以做到,就不要使用 js

颜色:值使用 小写字母 16进制;

颜色16进制尽量用简写。

/* bad */
.element {
    color: #ABCDEF;
    background-color: #001122;
}

/* good */
.element {
    color: #abcdef;
    background-color: #012;
}

css缩写:属性简写需要你非常清楚属性值的正确顺序,而且在大多数情况下并不需要设置属性简写中包含的所有值,所以建议尽量分开声明会更加清晰;margin 和 padding 相反,需要使用简写;

​ 常见的属性简写包括:

- `font`
- `background`
- `transition`
- `animation`
  // bad
  .box{
    border-top-style: none;
    font-family: palatino, georgia, serif;
    font-size: 100%;
    line-height: 1.6;
    padding-bottom: 2em;
    padding-left: 1em;
    padding-right: 1em;
    padding-top: 0;
  }

  // good
  .box{
    border-top: 0;
    font: 100%/1.6 palatino, georgia, serif;
    padding: 0 1em 2em;
  }

声明应该按照下表的顺序
左到右,从上到下

元素选择器应该避免在 scoped 中出现

官方文档说明:在 scoped 样式中,类选择器比元素选择器更好,因为大量使用元素选择器是很慢的。

# 分类的命名方法

使用单个字母加上"-"为前缀

布局(grid)(.g-);

模块(module)(.m-);

元件(unit)(.u-);

功能(function)(.f-);

皮肤(skin)(.s-);

状态(.z-)。

# 统一语义理解和命名

布局(.g-)

语义 命名 简写
文档 doc doc
头部 head hd
主体 body bd
尾部 foot ft
主栏 main mn
主栏子容器 mainc mnc
侧栏 side sd
侧栏子容器 sidec sdc
盒容器 wrap/box wrap/box

模块(.m-)、元件(.u-)

语义 命名 简写
导航 nav nav
子导航 subnav snav
面包屑 crumb crm
菜单 menu menu
选项卡 tab tab
标题区 head/title hd/tt
内容区 body/content bd/ct
列表 list lst
表格 table tb
表单 form fm
热点 hot hot
排行 top top
登录 login log
标志 logo logo
广告 advertise ad
搜索 search sch
幻灯 slide sld
提示 tips tips
帮助 help help
新闻 news news
下载 download dld
注册 regist reg
投票 vote vote
版权 copyright cprt
结果 result rst
标题 title tt
按钮 button btn
输入 input ipt

功能(.f-)

语义 命名 简写
浮动清除 clearboth cb
向左浮动 floatleft fl
向右浮动 floatright fr
内联块级 inlineblock ib
文本居中 textaligncenter tac
文本居右 textalignright tar
文本居左 textalignleft tal
垂直居中 verticalalignmiddle vam
溢出隐藏 overflowhidden oh
完全消失 displaynone dn
字体大小 fontsize fs
字体粗细 fontweight fw

皮肤(.s-)

语义 命名 简写
字体颜色 fontcolor fc
背景 background bg
背景颜色 backgroundcolor bgc
背景图片 backgroundimage bgi
背景定位 backgroundposition bgp
边框颜色 bordercolor bdc

状态(.z-)

语义 命名 简写
选中 selected sel
当前 current crt
显示 show show
隐藏 hide hide
打开 open open
关闭 close close
出错 error err
不可用 disabled dis

# SASS 规范

当使用 Sass 的嵌套功能的时候,重要的是有一个明确的嵌套顺序,以下内容是一个 SCSS 块应具有的顺序。
当前选择器的样式属性
父级选择器的伪类选择器 (:first-letter, :hover, :active etc)
伪类元素 (:before and :after)
父级选择器的声明样式 (.selected, .active, .enlarged etc.)
用 Sass 的上下文媒体查询
子选择器作为最后的部分

  .product-teaser {
    // 1. Style attributes
    display: inline-block;
    padding: 1rem;
    background-color: whitesmoke;
    color: grey;

    // 2. Pseudo selectors with parent selector
    &:hover {
      color: black;
    }

    // 3. Pseudo elements with parent selector
    &:before {
      content: "";
      display: block;
      border-top: 1px solid grey;
    }

    &:after {
      content: "";
      display: block;
      border-top: 1px solid grey;
    }

    // 4. State classes with parent selector
    &.active {
      background-color: pink;
      color: red;

      // 4.2. Pseuso selector in state class selector
      &:hover {
        color: darkred;
      }
    }

    // 5. Contextual media queries
    @media screen and (max-width: 640px) {
      display: block;
      font-size: 2em;
    }

    // 6. Sub selectors
    > .content > .title {
      font-size: 1.2em;

      // 6.5. Contextual media queries in sub selector
      @media screen and (max-width: 640px) {
        letter-spacing: 0.2em;
        text-transform: uppercase;
      }
    }
  }

# 特殊规范

对用页面级组件样式,应该是有作用域的 对于公用组件或者全局组件库,我们应该更倾向于选用基于 class 的 BEM 策略

  <style lang='scss'></style> // bad

  <!-- 使用 scoped 作用域 -->
  <style lang='scss' scoped></style> // good

  <!-- 使用 BEM 约定 -->
  <style> // good
  .c-Button {
    border: none;
    border-radius: 2px;
  }

  .c-Button--close {
    background-color: red;
  }
  </style>
笔试题

笔试题