# 前端开发规范
这个文档主要提供项目开发规范文档
# 命名规范
# 🔆 前端命名规范
1、项目名称
全部采用小写方式,以横线分隔或以下划线分隔
例:my-project-name
2、目录名称:有复数结构时,要采用复数命名法
例:scripts, styles, images, datas
4、文件名称:js文件名、scss文件名:采用中间连字符(*+"-"+*)
例:account-model.js、account-model.scss
5、vue文件名:中间连字符
例如:account-model/index.vue,account-model/components/page.vue
6、vue页面中的 name 属性:中间连字符 (name必填且唯一)
例如:y-title
7、文件夹名称:中间连字符
例如:my-document
8、data变量:小驼峰。例如:dataName:'',根据不同类型添加初始数据声明:
1)对于初始值是字符串类型的字段:userName:''
2)对于初始值是 数组类型 的字段:userList:[]
3)对于初始值是 对象类型 的字段:userInfo:{} 或时间对象:nowTime:new Date()
4)对于初始值是 布尔类型 的字段:isUserEdit:false 或 isUserEdit:true
5)对于初始值是 数字类型 的字段:userNum:0 或没有初始值的时候 userNum:NaN
9、方法命名:小驼峰
例如:myMethod()
10、组件引入:大驼峰
例如:import GCardHeader from '@/components/g-card-header/index.vue'
components: {
GCardHeader,
}
11、样式选择器命名:class和id
1)、类名命名=>单词+’-’+单词,如fine-home。连字符 '-'
2)、Id命名=>单词+’_’+单词,如fine_home。下划线连接
12、图片命名规范
1)、不要用拼音,尽量使用英文
2)、统一使用下划线 nav_right_back.png
3)、注意区分倍图@2x 和@3x 的后缀,例如banner_@2x.png
4)、图片的名称分为头尾两部分,用下划线隔开,
a、头部表示此图片的大类性质,例如广告,标志,菜单,按钮等
banner:放置在页面顶部的广告,装饰图案等长方形的图片
logo:标志性的图片
button:在页面上位置不固定,并且带有链接的小图片
menu:在页面中某一位置连续出现,性质相同的链接栏目的图片
pic:装饰用的图片
title:不带链接表示标题的图片
b、尾部结合应用具体命名,比如:
banner_sohu.gif, banner_sina.gif
menu_aboutus.gif,menu_job.gif
title_news.gif
logo_police.gif
pic_people.gif
# 1.组件命名规范
- 名称不能重复 (强制)
- 名称要有意义,做到见名知意 (强制)
- 不能使用拼音命名 (强制)
# 2.data 变量命名规范
data 属性名应该尽量能够做到见名知意,一般来说需要突出两到三个重点:
- 这个变量是关于什么业务行为的?
- 这个变量是关于什么组件的?
- 这个变量是关于组件什么特性的?
- 加上变量注释
# 3.方法命名规范
事件方法命名格式 handleXxxxx, 其他方法命名格式 fnXxx,或方法功能含义命名
# 4.路由规范
1、路由命名由两部分组成:模块名+具体功能名。命名:连字符'-'链接,例如:
{
path: "/login-module/login", //登录页,命名:连字符'-'链接
name: "login",
meta: {
needLogin: false,
title: "登录页"
},
component: () => import(/* webpackChunkName: "loginModule" */"@/views/login-module/login/index.vue")
},
{
path: "/login-module/reset-pwd", //重置密码页,命名:连字符'-'链接
name: "reset-pwd",
meta: {
needLogin: false,
title: "重置密码页"
},
component: () => import(/* webpackChunkName: "loginModule" */"@/views/login-module/reset-pwd/index.vue")
}
//路由嵌套
{
path: "/role-management",
name: "role-management",
component: () => import(/* webpackChunkName: "setting" */ "@/views/setting-module/role-mangement"),
redirect: "/role-management/set-auth",//该文件夹下默认打开的路由
meta: {
title: "角色管理"
},
children: [
{
path: "/role-management/set-auth",
name: "set-auth",
component: () => import(/* webpackChunkName: "setting" */ "@/views/setting-module/role-mangement/components/set-auth.vue"),
meta: {
title: "角色权限设置"
}
}
]
},
2、路由目录
├─src # 源代码
│ ├─router # 存放路由文件
│ │ ├─common
│ │ │ └─index.js # 公共模块路由
│ │ ├─login
│ │ │ └─index.js # 登录模块路由
│ │ └─after-each.js # 路由拦截器:afterEach
│ │ └─before-each.js # 路由拦截器:beforeEach
│ │ └─index.js # 自动注册路由
# 🔆 图片使用规范
# Web 端
# 1、PNG/JPG/SVG 格式

# 方案一:如上图所示:
- 实际代码设置图片宽(
width
)高(height
)以 1 倍图的宽高进行展示;即上图案例中源文件下载宽高:180x180px
;页面代码设置宽高:90x90px
,提高图片展示清晰度。 - png 格式的 1 倍和 2 倍的展示效果对比如下:

# 方案二:
推荐使用 svg 格式,展示清晰度最高,文件小。svg 与 png 格式的 1 倍和 2 倍的展示效果对比如下:

web 端 svg 图片下载方式如下图:

# 移动端
注意:移动端下载的图片以 750px 设计稿为标准,代码设置的图片宽高就是下载下来的 2 倍图的宽高
# 方案一:
移动端推荐使用 svg 格式,展示清晰度最高,文件小。svg 与 750px 标准下的 png 格式 2 倍图的展示效果对比如下:

移动端端 svg 图片下载方式如下图:

# SVG 图片展示-使用方法
常用方式:
<img :src="require('@/assets/test.svg')" />
svg-icon 使用 svg-sprite-loader:
<svg-icon icon-class="test" />
# 🔆 接口使用规范
1、调用页面 test.vue,如下:
<script>
// 1、引入数据接口
import {commonApi} from "@/api";
export default {
name: "",
methods:{
/**
* @description:获取表格数据
* @param {type}
* @return:
* @author: chenyt
*/
getTableData() {
this.loading = true;
//2、Api方法,传入接口参数
commonApi.getListReset(this.pageData.listQuery).then(response => {
this.tableDatas = response.data.items;
this.pageData.total = response.data.total;
// Just to simulate the time of the request
setTimeout(() => {
this.loading = false;
}, 1.5 * 1000);
});
}
}
}
</script>
2、接口 Api 方法定义
//定义接口文件
import request from "@/utils/request";
const basePath = "/table";
// get
/**
* @description:获取重置数据列表
* @param {type}
* @return:
* @author: chenyt
*/
export function getListReset(params) {
return request({
url: `${basePath}/list2`,
method: "get",
params: params,
});
}
//post
/**
* @description:获取二维码
* @param {type}
* @return:
* @author: chenyt
*/
export const getQRCode = function(params) {
return request({
url: `${basePath}/getQRCode`,
method: "post",
data: params, // 如果请求方式不是post需要将data改为params
});
};
3、汇总在 index.js 中,提供按模块输出接口函数,模块命名:“*+Api”,对应 modules 下的模块名称,如下所示:
//接口暴露文件index.js
import * as loginApi from "./modules/login-api";
import * as commonApi from "./modules/common-api";
export { loginApi, commonApi };
4、目录结构
├─src # 源代码
│ ├─api # 存放api接口文件
│ │ ├─modules # 根据业务需求划分模块放置接口文件
│ │ │ └─common-api.js # 公共接口
│ │ │ └─login-api.js # 登录模块接口,’-api‘结尾,对应views下的页面模块命名
│ │ ├─axios.js # axios请求文件,配置统一请求设置和返回拦截
│ │ └─index.js # 向外暴露接口模块
# 🔆 assets
资源文件
1、存放图片资源文件,imgs 文件夹下
2、存放数据字典,data 文件夹下
3、根据 views 下的模块划分 imgs 文件夹内部的二级文件夹名称,与页面一一对应。
4、文件目录结构
├─src # 源代码
│ ├─assets # 存放页面静态资源文件
│ │ ├─imgs # 存放图片文件夹
│ │ │ ├─common # 公共图片文件夹
│ │ │ │ └─loading.gif # 加载gif
│ │ │ ├─login # 登录模块图片文件夹,根据大模块划分,存储模块下所有图片
│ │ │ └─logo.png # logo图片
│ │ ├─data # 数据文件
│ │ │ └─common-dict.js # 公用数据字典文件
# 书写规范
# 🔆 样式书写规范
1、组件样式请记住加上 scoped 或者命名空间,避免造成全局的样式污染
2、样式选择器应避免使用元素选择器, 推荐类选择器。划分为:header-*
,container-*
,footer-*
<style scoped lang="scss" type="text/scss">
.header-box { padding: 20px }
</style>
3、尽量给每个页面,添加一个父类。以“page-”开头,如下所示:
<template>
<div class="page-login"></div>
</template>
其他样式在此父类下编写
<style scoped lang="scss" type="text/scss">
.page-login {
padding: 20px
.other-class{
....
}
}
</style>
4、少量样式可以写在组件,大量样式需要引入样式文件。
5、全局的样式变量文件和样式文件,存储在styles
文件夹中
6、样式文件夹目录
├─src # 源代码
│ ├─styles # 存放页面公用样式文件
│ │ ├─iconfonts # 存放图标
│ │ ├─theme # 页面主题设置,一般用于重置vant-ui或者element-ui组件样式
│ │ │ └─resetui.less # 重置样式文件
│ │ └─animate.scss # 动画
│ │ ├─common.scss # 公用样式
│ │ ├─normalize.scss # 浏览器重置样式文件
│ │ └─common-params.scss # 全局样式变量
# 🔆 业务组件编写规范
根据业务编写的可复用组件,请务必对每个属性、方法添加注释。并且将组件的使用说明编写对应的 readme 文档。
# 🔆 组件文件目录规范
├─src # 源代码
│ ├─components # 存放业务组件
│ │ ├─global # 存放全局注册组件
│ │ │ ├─y-title # 全局注册组件’y-title‘
│ │ │ │ └─index.vue # 组件对应文件
│ │ │ │ └─README.md # 组件使用说明readme
│ │ │ └─y-banner # 全局注册组件’y-banner‘
│ │ ├─y-title # 组件’y-title‘
│ │ │ └─index.vue # 组件对应文件
│ │ │ └─README.md # 组件使用说明readme
│ │ └─index.js # 注册全局组件
- 1、组件文件夹命名 以“y-“开头。例如 y-title
- 2、全局注册放在 globle 文件夹下,实现自动注册
# 组件 README 文档编写格式参考
## 动画加载
### 如何使用
```js
this.$Loading.show()
this.$Loading.hide()
```js
### API
| name | 描述 | 参数 |
| ---- | ---- | -------- |
| show | 展示 | duration |
| hide | 关闭 | 无 |
### Options
| 参数 | 说明 | 类型 | 默认值 |
| -------- | ---------------------------------------------- | -------- | ------ |
| duration | 延迟多少秒自动关闭 当`duration`为0时不自动关闭 | `number` | 0 |
# 🔆 views
页面文件规范
在views
下添加业务页面,页面 template 中的标签控制长度,当某个模块例如弹窗模块标签行数很长,导致页面可读性低,应控制页面标签长度,独立此模块放在该文件夹下的 components 中。目录如下
├─src # 源代码
│ ├─views # 存放业务页面文件
│ │ ├─login-module # 根据业务划分页面存放模块
│ │ │ ├─login # 登录页面文件夹
│ │ │ │ └─components # 登录页面可分模块放置的文件
│ │ │ │ │ └─dialog-module.vue # 分割出来的弹窗模块组件
│ │ │ │ └─index.vue # 登录页面文件
│ │ │ └─reset-pwd # 重置密码,文件夹命名:用中间连字符“-”
│ │ │ └─index.vue
│ │ ├─other-module # 其他模块
│ │ │ ├─other # 其他模块页面
│ │ │ │ └─components # 其他模块页面业务模块文件
│ │ │ │ └─index.vue # 其他模块页面
│ │ │ └─reset-page # 其他模块
│ │ │ └─index.vue # 其他模块页面
│ │ │ └─style.scss # 样式文件很长的时候,另存在样式文件中
- 1、文件夹命名:用中间连字符“-”,以’-module‘结尾,划分模块。
- 2、页面划分过长的业务模块存放于 components 文件夹中
- 3、文件内容统一引入存放在 index.vue 中
- 4、样式文件很长的时候,另存在样式文件中
# 🔆 代码注释
- 页面基本信息注释
<!--
* @Description: 首页
* @Version: 0.1
* @Autor: chenyt
-->
- 页面方法注释
/**
* @description:初始化
* @param {type}
* @return:
* @author: chenyt
*/
# 提交规范
# 🔆 代码提交规范
# 1、代码提交必须包含提交类别
用于说明 commit 的类别,只允许使用下面 9 个标识:
- feat:新功能
- fix:修复 bug
- docs:撰写文档
- style:代码格式(不影响代码运行的变动)
- refactor:重构(既不是新增功能,也不是修改 bug 的代码变动)
- test:增加测试
- build:工程化
- chore:代码优化或辅助工具的变动
例如:fix:修改登录自动退出的 bug。
# 2、执行 npm run lint
规范 eslint 规则
# 3、提交合并
保证功能完整性,提交到个人开发分支远程后,合并到 develop 分支
# 🔆 代码分支管理统一
1、分支通常可以对应研发流程中不同的部署环境:
- tag -> 生产环境(production)
- master -> 预发/灰度环境(pre-production/staging)
- develop -> 测试环境(test)
- feature -> 线下调试/开发环境,例如:feature/cyt
2、使用过无用的分支定期清理掉
# 用户体验
若需求方无特殊要求,则按照以下规则。
# 🔆 前端表格规范 - 严格要求
# 颜色值
- UI 没有给出明确色值时,表头背景颜色值: #F0F2F5; 选中或鼠标悬停在某一行时,此行背景颜色值应为: #DEE9F5;
# 表格中数据展示应符合下述要求
- 表头数据 居中 展示
- 同一列文本数据长短不一致的应 居左 展示,例如单位名称、地址;
- 统一列数据长短基本一致的应 居中 展示,例如姓名、性别、日期、审核状态
- 金额、数字内容应 居右 展示,对应表头标题应使用 半角括号 注明单位,例如“金额(元)”
- 金额应保留两位小数点

# 表格交互应符合下述要求
- 表格数据较多时可显示拖动滑块; 宜根据操作需求,提供编辑功能;
- 表格列宽结合实际内容不能全部统一宽度;
- 主动询问了解表格数据量,询问是否需要做分页及其分页策略
# 表格展示
用于查询后的数据展示时,表格的第一列应为序号; 表格中使用多选框和单选框时,设置在序号左侧;
# 表格滚动条
滑动横向滚动条时保留重要字段;如操作区域、表头区域。
# 🔆 前端数据校验规范
# 身份证
- 号码长度验证:身份证长度仅存在 15 位或 18 位两种长度;
- 号码正确性验证:如身份证号为 18 位,可根据本体码与校验码得关系验证身份证号码输入有误(本体码包括地址码、出生日期码和顺序码,根据本体码,通过采用 ISO 7064:1983,MOD 11-2 校验码系统计算出校验码。);
- 根据 18 位与 15 位身份证号码编码规则及校验码算法,将 15 位身份证号码转换为 18 位身份证号码(a.出生日期码:15 位身份证号码中出生日期码为 4 位,其中年份代码仅有 2 位,如 590328,代表 1959 年生。b. 校验码:15 位身份证号码中无校验位。);
- 校验码为 X:因校验码为 X,实际上有大小写输入不同,请注意兼容或统一。
- 号码真实性:真实姓名和身份证号在公安系统进行匹配真实性。
# 手机号
- 第一位必须为数字 1;
- 第二位不能为 0/1/2;
- 数字长度必须为 11 位,多了少了都不行;
- 必须输入阿拉伯数字,其他数字、字母、汉字和符号均不可输入。
# 登录密码
如没特殊要求,为了方便老年人的同时,尽可能保证账户的安全性,密码长度为 6 到 8 位数字或字母或数字和字母组合,字母不区分大小写。不能输入汉字和各种符号。
# 电子邮箱
- 电子邮件的邮箱地址格式:用户标识符+@+域名;
- @之前必须有内容且只能是字母(大小写)、数字、下划线(_)、减号(-)、点(.);
- @和最后一个点(.)之间必须有内容且只能是字母(大小写)、数字、点(.)、减号(-),且两个点不能挨着;
- 最后一个点(.)之后必须有内容且内容只能是字母(大小写)、数字且长度为大于等于 2 个字节,小于等于 6 个字节。
# 金额
- 不能输入中文、特殊符号
- 只能输入一个点(.)
# 🔆 前端表单优化
# 1. 标签
- 表单中 label 一般不宜太长,尽量不换行(适当调整 label-width)。
- 必填项需标记“*”,若全为必填则不标记
# 2.输入域
- 输入框 带有 clearable 清空属性
<el-input
placeholder="请输入内容"
v-model="input"
clearable>
</el-input>
- 单选框、多选框:可以单击它或关联标签来激活/禁用它
<input type="checkbox" id="option1" /> <label for="option1">Option 1</label>
或者
<label for="option1">
Option 1
<input type="checkbox" id="option1" />
</label>
- 密码输入框 增加显示密码功能-右侧小眼睛图标,便于用户看到输入的错误。
# 3.触发校验
在完成一个字段后进行内联验证,比如当姓名输入框失去焦点后,再进行验证。 不要在输入过程中进行验证,否则用户还未输入完成会一直出现错误。
# 4.错误信息提示
输入域错误提示时,带上校验规则说明,如:
- "请输入用户名" 换成 "请输入字母开头,3-20 位的用户名"
- "请输入密码" 换成"请输入 6-20 位由字母大小写和数字组成的密码"
# 5.操作按钮
操作按钮通常分为主次按钮,如:提交和取消,保存和取消等。
- 按钮默认位置:左侧为次要线框按钮,右侧为主要色块按钮。
- 表单有清空/重置按钮等回退按钮。
- 查询表单建议重置按钮,清空表单同时触发查询。
# 6.键盘
请使用与预期输入相匹配的键盘,如手机号使用数字键盘
# 🔆 避免重复请求 - 重要
- 业务提交时,需要使用带遮罩的 loading,避免用户重复提交
- 封装全局请求方法,避免接口重复请求
// 使用示例,第一个参数name不可重复
export function queryUnitGroupByPage(data = {}, config = {}) {
return yRequest.post("unitSettingQuery", "/gbjd/Unit/queryUnitGroupByPage", data, config)
}
/*
* @Description: 封装全局请求方法
* @Autor: syx
*/
import axiosRequest from "./common-axios"
const GLOBAL_REQUEST_OBJ = {}
function request(name, params) {
return new Promise((resolve, reject) => {
if (GLOBAL_REQUEST_OBJ[name] && GLOBAL_REQUEST_OBJ[name] === "requesting") {
return
}
GLOBAL_REQUEST_OBJ[name] = "requesting"
axiosRequest(params).then(result => {
delete GLOBAL_REQUEST_OBJ[name]
resolve(result)
}).catch(err => {
delete GLOBAL_REQUEST_OBJ[name]
reject(err)
})
})
}
["get", "post"].forEach(type => {
request[type] = (name, ...params) => {
return new Promise((resolve, reject) => {
if (GLOBAL_REQUEST_OBJ[name] && GLOBAL_REQUEST_OBJ[name] === "requesting") {
return
}
GLOBAL_REQUEST_OBJ[name] = "requesting"
axiosRequest[type].apply(this, params).then(result => {
delete GLOBAL_REQUEST_OBJ[name]
resolve(result)
}).catch(err => {
delete GLOBAL_REQUEST_OBJ[name]
reject(err)
})
})
}
})
export default request
# 🔆 其他优化
# 1.手型鼠标
链接或可点击区域,光标移入变成手型鼠标
# 2.点击区域
提供足够大的点击区域,如标题和对应图标都应有绑定事件。移动端谷歌建议最小区域为 48x48px 可作为参照。
# 3.图片显示优化
图片尺寸、比例与显示比例不一致,可使用 object-fit:cover 优化,避免图片拉伸变形
# 4.弹窗
弹窗宽度:同类型弹窗尽可能宽度保持一致,常见 PC 端弹窗宽度尺寸为:640px、720px、960px;
弹窗高度:整个弹窗高度不要超过
90vh
, 可以设置.el-dialog__body
的最大高度, 最小高度也不小于260px;
.el-dialog__body {
padding: 16px 24px;
max-height: 64vh; // 最大高度设置
min-height: 260px; // 最小高设置
overflow: auto;
}
对比如下: