Web前端编程规范
说明:本文于2019-09-22整理,到目前一些内容已经不适用。比如bootstrap,后面多用element-UI、antd等UI组件库。jQuery库等也逐渐不用了。vue2到vue3发生了很多变化,react框架在项目中也用得多了。精力原因,未对本文内容进行更新。
1.编码规范
1.1命名规范
整体:尽量避免缩写,使用完整的英文单词组合,如使用device而不是dev。
文件夹、文件命名:全部小写、多个单词单横线连接。
JavaScript:变量、函数统一用驼峰命名法,如:areaList 、addUser、getDevice
CSS:样式名全部小写,使用连字符“-”连接 .card-header .card-body。不要用下划线连接,不要使用驼峰命名法或帕斯卡命名法。
HTML:标签、属性、样式等全小写,用连字符“-”连接。
id 、ref 用下划线“_”连接。
1.2 JavaScript语言规范
1.var、let与const
1)var 常规的定义变量,存在变量提升问题,即变量的作用域超出其代码块范围。
内部"{}"中声明的var 变量会覆盖外部的var声明的变量
2)let 通过let定义的变量,作用域是在块级或是子块中
内部"{}"中声明的letTest和外部的letTest不是同一个变量
同一个作用域内let重复声明会报错
let不能在js中使用,是es6的语法,需要在js中使用就必须使用严格模式:'use strict';
3)const是常量,定义后,不可修改变量的值
2. 除公共脚本外,一个html文件应该对应一个文件名相同的js文件。
3. js文件中,自定义方法时候,方法名命名应该名词或者动词加名词构成,若需要传入参数时,应添加必要的参数说明。如:
/*
* 初始化驱动函数
*
* @param {number} age 年龄值
* @param {string} name姓名
*
* TODO 描述。。。。。
*/
function setAge(param){
…
}
4.对变量进行必要的声明,特别是方法内部出现的变量,若不定义,浏览器会认为是全局变量。如:
function example(){
age = 20; //变量未声明吗,age会被认为是全局变量,其他方法也调用到它
var anme = "Tom"; //声明变量,作用范围仅限于该方法内。
…
}
5.变量的命名使用名词。使用驼峰命名法。全局变量首字母大写,局部变量首字母小写。
6.简单的if——else运算,可用三目运算符代替。
如:
var age = 20;
var name;
if(age > 30){
name = “Tom”
}else{
name = “Jack”
}
用三目运算式表示为:
var name = age > 30 ? “Tom”:“Jack”;
7.对于嵌套的方法,尽量不要直接使用this关键字,容易产生混淆。
如:
function age(name){
console.log(this.name);
function setName(name){
console.log(this.name); //这个this是谁的,不直观。
}
this.setName(name);
}
建议修改为:
function age(name){
var self = this;
console.log(self.name);
function setName(name){
console.log(this.name);
}
self.setName(name); //self代替了this。
}
8. 当在导航切换的逻辑里给元素绑定事件时,记得先移除需要绑定的事件,再接着绑定需要绑定的事件。这样做是为了保证事件只有一个,若存在多个相同事件,则会重复触发事件,造成必要的错乱。如:按钮收起又展开。
9.js中,false,0,“”,undefined,null,NaN在if判断中,都会被认为是false,所以判断一个数组是否为空时,可以这样写:
if(array.length){
//数组不为空
}
10.在浏览器环境下,对js进行断点调试时,可以在浏览器的开发者工具的Console工具栏,输入可以观测的参数并按回车打印,Console工具栏将打印出参数的值。若是在Console里输入其他逻辑代码,浏览器将会运行这段代码,并返回结果。
1.3 CSS语言规范
1)在css文件开头,添加:@CHARSET "UTF-8";保证样式表格式与引用的html文件保持相同格式。
2)css选择器避免嵌套层级过多,过多的嵌套会延长选择器处理时间,延长样式响应时间,建议选择器层级不超过3级。
3)避免在选择器里叠加使用class选择器和id选择器,如:#map.map。
4)css中,不同类型的选择器,权重不一样。如果元素选择器的权重是1,那么通配选择器*的权重为0,伪类选择器的权重是1,类选择器的权重是10,id选择器的权重是100。权重越低越容易被覆盖。但是有个毕竟特殊标志——!important。作用在具体某个样式声明里,如:a{color:”#f00” !important;},意味着选择到的所有a元素,color样式声明将无视选择器等级的差距,强制修改颜色为:“#f00”。可以认为”!imortant”的权重是最高的,达到1000。
5)css样式声明顺序,相关属性应该为一组,推荐样式编写顺序:
Positioning(位置)
Box model(盒模型)
Typographic(排版印刷)
Visual(视觉效果)
由于定位(positioning)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在首位。盒模型决定了组件的尺寸和位置,因此排在第二位。
6)其他属性只是影响组件的内部(inside)或者是不影响前两组属性,因此排在后面。
url(),属性选择符,带空格的属性值使用引号包住。如:
div{
background: url("img.png");
}
.selector[type="text"]{
font-family: "Arial Narrow";
}
7)媒体查询(Media query)的位置。将媒体查询尽量放在相关样式规则的附近,不要分离打包到一个单独的文件里或者文档的底部,时间久了,样式可能会被遗忘,需要修改时不方便查找。
8)文本对齐。如果是纯数字或者纯汉字下,页面很容易对齐,但是当文本里参杂着中英文时,文字排版容易出现拉伸,可以使用以下的样式属性进行断词处理,
p{
word-break:break-all;
}
9)当自定义的样式不是很规范或者不容易直观看出是做什么的,应该添加必要的注释说明,方便日后维护。
1.4 Html语言规范
1)文件名称以名词或者多个名词加连接符组成,如:home.html, center-city.html。
2)除特殊需要,统一使用HTML5的标准文档类型:<!DOCTYPE html>;并添加字符集声明:<meta charset="utf-8">;
3)在title标签之后,先引入css样式表,再引入js脚本。样式表在同级下,后面引入的样式会覆盖前面的样式,故先引入框架文件,如bootstrap.css,再引入公共样式表,如theme.css,最后引入自定义的样式表。js脚本需要先引入基础的框架,如jquery.js再引入在此框架上衍生的脚本,如:jQuery-ui.js,最后引入自定义的脚本。
在调用CSS和JavaScript时,type属性可以省略不写。如:
<link type="text/css" rel="stylesheet" href="base.css" />
<script type="text/javascript" src="base.js"></script>
可简写为:
<link rel="stylesheet" href="base.css" />
<script src="base.js"></script>
4)使用合理的方式嵌套标签。确保标签能够正确闭合。对于块级元素,如,<div>、<p>、<h1>、<ul>、<li>标签等,其父标签建议用块级元素。块级元素的典型特征是在默认样式时,会独占一行。而行内元素在默认样式下,不会独占一行。
此外,行内元素里不建议包含块级元素,而块级元素可以块级元素、行内元素、可变元素。
块级元素列表 |
|
<address> |
定义地址 |
<caption> |
定义表格标题 |
<dd> |
定义列表中定义条目 |
<div> |
定义文档中的分区或节 |
<dl> |
定义列表 |
<dt> |
定义列表中的项目 |
<fieldset> |
定义一个框架集 |
<form> |
创建 HTML 表单 |
<h1> |
定义最大的标题 |
<h2> |
定义副标题 |
<h3> |
定义标题 |
<h4> |
定义标题 |
<h5> |
定义标题 |
<h6> |
定义最小的标题 |
<hr> |
创建一条水平线 |
<legend> |
元素为 fieldset 元素定义标题 |
<li> |
标签定义列表项目 |
<noframes> |
为那些不支持框架的浏览器显示文本,于 frameset 元素内部 |
<noscript> |
定义在脚本未被执行时的替代内容 |
<ol> |
定义有序列表 |
<ul> |
定义无序列表 |
<p> |
标签定义段落 |
<pre> |
定义预格式化的文本 |
<table> |
标签定义 HTML 表格 |
<tbody> |
标签表格主体(正文) |
<td> |
表格中的标准单元格 |
<tfoot> |
定义表格的页脚(脚注或表注) |
<th> |
定义表头单元格 |
<thead> |
标签定义表格的表头 |
<tr> |
定义表格中的行 |
行内元素列表 |
|
<a> |
标签可定义锚 |
<abbr> |
表示一个缩写形式 |
<acronym> |
定义只取首字母缩写 |
<b> |
字体加粗 |
<bdo> |
可覆盖默认的文本方向 |
<big> |
大号字体加粗 |
<br> |
换行 |
<cite> |
引用进行定义 |
<code> |
定义计算机代码文本 |
<dfn> |
定义一个定义项目 |
<em> |
定义为强调的内容 |
<i> |
斜体文本效果 |
<img> |
向网页中嵌入一幅图像 |
<input> |
输入框 |
<kbd> |
定义键盘文本 |
<label> |
标签为 input 元素定义标注(标记) |
<q> |
定义短的引用 |
<samp> |
定义样本文本 |
<select> |
创建单选或多选菜单 |
<small> |
呈现小号字体效果 |
<span> |
组合文档中的行内元素 |
<strong> |
语气更强的强调的内容 |
<sub> |
定义下标文本 |
<sup> |
定义上标文本 |
<textarea> |
多行的文本输入控件 |
<tt> |
打字机或者等宽的文本效果 |
<var> |
定义变量 |
可变元素素列表--可变元素为根据上下文语境决定该元素为块元素或者内联元素 |
|
<button> |
按钮 |
<del> |
定义文档中已被删除的文本 |
<iframe> |
创建包含另外一个文档的内联框架(即行内框架) |
<ins> |
标签定义已经被插入文档中的文本 |
<map> |
客户端图像映射(即热区) |
<object> |
object对象 |
<script> |
客户端脚本 |
5)class和id应该以其功能或者内容命名,不要用表现形式命名。如“#map”、“.text-center”。尽量少用id属性,id属性用于标记标签在页面上是唯一的,需要用时,确保id在当前页面只会出现一次。class与id单词字母用小写,多个单词组成时,采用连接符“-”连接。
6)属性顺序。编写标签时,标签的属性应该按照统一的顺序,保证易读性。如:
<div id=”map” class=”text-center” name=”map” title=”地图”></div>
建议顺序:
id
class
name
data-xxx
src, for, type, href
title, alt
aria-xxx, role
7)标签的属性值,统一使用双引号。如:<div id=”map” title=”地图”></div>。使用js动态生成html标签时,属性值也使用双引号包裹。如:
var map = ‘<div id=”map” title=”地图”></div>’;
$(map).appendTo($(“body”));
8)引用了框架样式时,尽量先使用量框架提供的样式。如需要文本居中,同时也引入了bootstrap.css框架的样式,可在class属性中添加“text-center”来实现文本居中,减少需要自定义的css样式代码量。
2.Web页面需求规格
以下规约主要适用后台管理页面。
2.1 整体布局和风格
页面主题样式定义在theme.css 中,各页面优先使用全局主题类样式。
页面结构布局使用bootstrap样式中的card 、card-header 、card-body。
页面主题色为bootstrap中info,查询、确定、保存等按钮用btn-info(天蓝色),取消按钮用btn-secondary(灰色),删除按钮用btn-danger(红色)。
2.2 头部区域(card-header)
使用theme.css中定义的样式,不要自定义。
标题:使用header-title样式
副标题:使用header-note样式
头部区域的操作按钮:靠右对齐,使用header-btn样式
2.3 检索
2.3.1 搜索框
直接使用在theme.css中全局定义的样式。要求:
支持回车执行检索、风格统一。
列表区域搜索靠右对齐,参考户管理列表页的html代码。
弹出窗体的搜索框占满窗体,参考用户修改中选择区域的html代码。
弹出窗体中有靠右布局的可单独处理。
2.3.2 多条件检索
条件输入框和选项框左对齐排列,操作按钮右对齐排列。
2.4 数据列表
隔行变色,使用table-striped样式。
最后一列操作按钮右对齐。
其他列中有操作按钮的,未说明则居中对齐。
文本为做说明的左对齐。
所有列表展示应使用统一的分页组件,支持分页查询,每页统一设定为8条。
所有删除操作,都需要二次弹窗确认。
2.5 添加/修改弹出窗
样式统一,参考用户添加、修改。使用垂直居中样式:modal-dialog-centered
不需要表单校验的:根据实际情况决定是否使用大的弹窗样式,建议使用栅格布局。
需要表单校验的样式:使用大的弹窗样式:modal-lg,使用form标签,dialog-edit、flex、left-label、flex-right这一组样式。
编辑界面通常都应该做非空校验,最小长度、最大长度、数字、电话号码、邮箱等方面的校验。提交前做整体校验,通过后执行提交。
保存、修改、删除等操作失败或成功,都应该进行弹窗提示。使用同一风格的弹窗。
3.Web页面开发规范
3.1 框架
3.1.1 项目框架和技术栈
熟悉框架,数据工程目录结构,在框架体系下开发。
优先使用组件,其次嵌套路由,有外部网页等特殊情况才考虑使用iframe。
熟悉框架中已集成的插件及用法,插件清单:
外部引用的插件(plugins目录下):
htlib ht-editor库
jquery-validation 输入校验
jquery-upload-file 多文件上传
limarquee 跑马灯
select2 下拉选项框,支持多选、检索
ztree 树插件,支持拖拽、节点搜索
npm包管理器安装的插件(node_modulse目录下):
jquery jquery库
jquery-ui-dist jQuery UI
bootstrap UI库
bootstrap-table 表格样式
element-ui UI库,目前主要用到alert弹窗
clone 支持js对象的深拷贝
js-md5 MD5加密
axios 网络请求
vue-cookies Cookie库
vue-datetime 日期和时间插件
vue-moment 时间格式化插件,支持计算时间差
vue-i18n 多语言库
3.1.2 Vue框架使用规范
分而治之:
属性封装到data中,格式化处理放到filters中,业务功能封装成方法放到methods中
其他部分通过this使用属性和方法。
避免直接在created、mounted等生命周期的钩子里写具体功能的实现代码。如:
export default {
//定义常用的属性
data() {
return {
pageInfo:{
},
condition:””
}
},
// 生命周期钩子 创建
created() {
loadData();
},
// 生命周期钩子 Dom加载完成
mounted() {
initSelect2();
},
// 过滤器,用来对数据绑定的属性进行格式化。
filters:{
orderStatusDesc: function (value) {
switch(value){
case 0:
return "未分配";
case 1:
return "已分配";
}
}
},
//监听路由或属性变化
watch:{
'$route': "reload"
},
methods: {
// 业务相关的方法、过滤器中无法完成的的格式化
}
}
3.2 UI库
3.2.1 Bootstrap
1)BootStrap组件使用
优先使用bootstrap提供的各种组件,没有提供的再自行开发。
详见2.1节对于整体布局的说明。
2)BootStrap布局
避免使用absolute定位,绝对定义脱离了文档流,易引起冲突,增加复杂度和维护难度。
n flex快速实现自适应
自适应两列布局:一列固定宽度,一列自适应。flex和flex-right是项目中已定义的全局样式,直接使用。
<div class="flex">
<div id="left-menu"></div>
<div class="flex-right"></div>
</div>
同理,可用flex快速实现自适应的两行或多行布局。
栅格布局:将区域划分为等宽的12列。使用col-指定当前元素占用的列数。
默认使用col-,适应特定尺寸屏幕的还可以使用以下栅格样式:
· col-xs- (超小屏幕 手机 <768px)
· col-sm- (小屏幕 平板 ≥768px)
· col-md- (中等屏幕 桌面显示器 ≥992px)
· col-lg- (大屏幕 大桌面显示器 ≥1200px)
组合使用col-和col-xs-可以适应不同尺寸屏幕的布局需求。
<div class="row">
<div class="col-2"></div>
<div class="col-3"></div>
<div class="col-7"></div>
</div>
栅格布局可嵌套使用。
<div class="row">
<div class="col-2"></div>
<div class="row col-10">
<div class="col-4"></div>
<div class="col-8"></div>
</div>
</div>
表单样式 form-control
应用了form-control表单元素,会占满父级容器的宽度。
3)BootStrap样式
优先使用bootstrap提供的对齐、字体等布局和样式类,避免自定义很多样式类,避免在html元素上直接写行内样式代码(style)。
对齐样式:text-left、text-center、text-right
样色样式:text-primary、text-secondary、text-success、text-danger、text-warning、 text-info
bg-primary 、bg-secondary 、bg-danger 、bg-light
btn-primary btn-danger btn-secondary btn-info
字体样式:font-weight-bold、 font-weight-normal、 font-weight-light、 font-italic
3.2.2 Element-UI
目前主要用到弹窗组件。
成功提示:在点击“确定”的回调中处理modal-dialog的关闭。如:
this.$alert("修改成功!", '提示信息',{
confirmButtonText: '确定',
callback: action => {
$('#material-info').modal('hide');
}
});
错误提示,如:
this.$alert(data.message, '提示信息');
3.3 页面开发
3.3.1 页面布局规范
div的层级尽量要少,可有可无的删除。
除数据列表外,table布局和div布局两种,优先选择div布局。
多列布局,推荐使用bootstrap的栅格布局,且可嵌套。
栅格布局不能满足需求的,可考虑使用flex布局。
3.3.2 Vue属性使用规范
各个子模块,style标签使用scoped声明作用域。如<style scoped ...></style>
Vue for循环,需要使用 :key="item.id"来绑定一个唯一值,便于双向绑定场景下页面局部刷新。
:key=""使用对象的一个字段,不要使用整个对象。如果绑定对象,会导致打包后运行报错。
<option v-for="role in roleList" :key="role" :value="role.role_id" >
<option v-for="role in roleList" :key="role.role_id" :value="role.role_id" >
{{role.role_name}}
</option>
3.3.3 组件间通讯规范
使用connect.$emit触发事件;
使用connect.$on监听事件;
使用connect.$off取消事件的监听。
注意:配套使用connect.$on和connect.$off,在Vue的生命周期钩子created中监听,在生命周期钩子destroyed中取消监听。
3.3.4 接口调用规范
使用axios调用接口,需要加上.catch代码块,否则如果调用失败,js脚本错将中断整个页面后续代码的执行,即页面卡死。
this.http.get(url)
.then(res => {
// todo
})
.catch(err=>{
console.log(err)
});
3.4 响应式规范
3.4.1 字体 rem
使用rem单位,便于通过调整根元素的字体大小,实现整个页面字体的统一调整。
app.css 已经设置整个页面body的font-size。
所有设置字体大小的地方,以rem为单位,通过相对值来设置。 如:font-size:1.5rem,相当于body元素的字体大小的1.5倍。
3.4.2 为不同设备屏幕应用不同样式
// Small devices (landscape phones, 576px and up)
@media (min-width: 576px) { ... }
// Medium devices (tablets, 768px and up)
@media (min-width: 768px) { ... }
// Large devices (desktops, 992px and up)
@media (min-width: 992px) { ... }
// Extra large devices (large desktops, 1200px and up)
@media (min-width: 1200px) { ... }
4.调试规范
调用接口尽量不要写console.log打印结果,可在network中查看响应结果。
使用开发工具断点调试,避免代码中大量的console.log,只保留少量必要的日志。
调试日志的可读性。
(1)推荐使用关键字+内容。如:
console.log(“userId:”+this.$cookie.get(“userId”))
(2)需要打印对象,关键字和内容分两次打印,以免日志中只显示[object]:
console.log(“userInfo:”)
console.log(user)
验收完成的模块,应删除该模块所有alert、log、注释的代码。
5.设计思想和原则
5.1面向对象思想
封装、继承、多态。使用类、对象封装代码,注意模块间的解耦。
5.2软件设计原则
1.职责单一原则
2.开放封闭原则(扩展开发、修改封闭)
3.里式转换原则 (父类能出现的地方子类也可以出现)
4.依赖倒置原则
5.接口分离原则
接口粒度要小,组合使用。
类似有前端类样式的组合使用,避免在一个定义里实现所有样式效果。
6.迪米特法则
知识最少原则。
只向外开放必要的接口、方法、属性等。
5.3总体要求
遵循软件设计思想,遵循Web页面开发规范,多利用框架现有的通用库和全局样式,保持统一风格,力求代码、注释、日志简洁。