Web前端编程规范

作者:陆金龙    发表时间:2023-07-01 10:42   

关键词:  

说明:本文于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页面开发规范,多利用框架现有的通用库和全局样式,保持统一风格,力求代码、注释、日志简洁。