web前端开发规范

web开发约束

项目结构:

vue项目结构

    |-- 项目名
                |-- static      开发相关静态文件
                            |-- fonts       字体样式的存放目录
                            |-- image       全局共用的img图片目录
                            |-- js      全局共用的js目录
                            |-- other       全局共用的其他文件目录(如果需要,可选)
                            |-- ...
                |-- src         开发内容
                            |-- api    api请求server的目录
                            |-- components    全局共用组件的目录
                                         |-- dependent  有依赖于第三方的自行构建的全局组件 组件使用前缀 dep-
                                         |-- independent    无依赖的自行构建的全局组件 组件使用前缀 indep- 具有可靠的移植性和独立性
                            |-- config    默认配置的目录
                                        |-- constant.js     共用常量配置文件
                                        |-- translate.js        翻译配置文件
                                        |-- fragment.js         配置碎片
                                        |-- ...
                            |-- frame   自定义框架的目录
                            |-- global   全局引用目录
                            |-- doc     用于存放项目文档(如果需要,可选)
                            |--mixin   vue混合的目录
                            |-- page    单页面应用的目录
                                        |-- 业务目录
                                                    |-- 业务模块
                                                                |-- _js     此业务私有的js
                                                                |-- _img        此业务私有的img(如果需要,可选)
                                                                |-- ...
                                                    |-- _共用模块名      业务私有的共用模块必须使用_前缀
                                                    |-- doc     用于存放业务文档(如果需要,可选)
                                        |-- ...
                            |-- routes    vue路由的目录
                            |-- style    单页面应用样式的目录
                            |-- utils    项目工具型函数的存放目录
                                        |-- custom-methods.js      自定义的共用方法
                                        |-- validator.js        自定义的验证方法
                                        |-- ...
                            |-- datajson        引入本地json的目录,谁引入则在建立其对应的目录中存放
                            |-- fragment        公用碎片

vue命名约束

语义化和命名

应以功能或内容命名,不以表现形式命名;
命名-缩写规范使用业界熟知的或者约定俗成的。
常量采用全部大写,单词间下划线分隔的命名方式。
变量采用驼峰命名法。
全局属性或者引入文件采用$驼峰命名法进行命名。
私有属性、变量和方法以下划线 _ 开头,由多个单词组成的 缩写词。在命名中,根据当前命名法和出现的位置,所有字母的大小写与首字母的大小写保持一致。
枚举变量 使用 Pascal 命名法。(与骆驼命名法类似。只不过骆驼命名法是首字母小写,而帕斯卡命名法是首字母大写)
对于vue组件的props命名采用驼峰命名法,对于data(){}中定义的变量采用下划线,特殊的功能需要加入特殊的下划线后缀或前缀。

props: {
    routerJump: String // props命名采用驼峰命名法
}
data () {
    return {
                // data(){}中定义的变量采用下划线,特殊的功能需要加入特殊的下划线后缀
        city_id: 100101,  // _id标记id
        city_name '北京' , // _name标记_id对应的结果
        idcard_photo: null,  // _photo标记图片
        re_evaluate: '重新评估', // re_重新
        is_show: false // is_
    }
}

对于vue组件属性和组件引用采用中划线的方式,枚举变量 使用 Pascal 命名法

<label-content :value="auto_query_condition" label-width="120px" :inline="true" :border="true" label-position="left" label-item-width="400px" all-background="#fbfdff"></label-content>

import AudioGallery from './mode/audio-gallery.vue' // 音频-Pascal 命名法
export default {
    components: {'audio-gallery': AudioGallery} // 组件引用采用中划线
}

vue方法名,计算属性名采用驼峰命名法

computed: {
    conversion () {}
},
methods: {
    checkFind () {}
}

选项顺序:

export default {
    name: '',
    mixins: [], // 混入
    components: {}, // 组件
    model: {},
    props: {},
    data () {
        return {}
    }, // 数据
    created () {}, // 创建周期
    mounted () {}, // dom挂载周期
    computed: {}, // 计算属性
    watch: {}, // 监听器
    methods: {}, // 方法
    filters: {}, // 过滤
    directives: {}, // 指令
    destroyed () {} // 实例销毁周期
}

vue-router

引用形式

const Frame = {template: '<router-view></router-view>'}
import TemplateList from '@/page/template/list/list.vue'
import TemplateAddEdit from '@/page/template/add_edit/add-edit.vue'

export default [
    {
        path: '/template',
        name: '模板演示',
        component: Frame,
        children: [
            {
                path: 'list',
                name: '模板列表',
                meta: { linkable: true }, // 元信息
                props: { ruterModule: '模板列表' }, // 路由组件传参
                component: TemplateList
            },
            {
                path: 'edit/:templateId', // id参数必须唯一,例如用户模块下必须使用userId
                name: '编辑模板',
                meta: { linkable: true }, // 元信息
                props: { ruterModule: '编辑模板' }, // 路由组件传参
                components: TemplateAddEdit
            }
        ]
    }
]

vuex

state采用驼峰命名,

getter

采用驼峰命名,以get开头

getAllWords (state, getters, rootState, rootGetters) {
    return [...state.words]
  }

mutations

采用大写明明

export const DATA_RESET = 'DATA_RESET' // 数据重置
[types.DATA_RESET] (state) { // 数据重置
    state.words = []
  }

约束-后缀

// 加载:_LOADING,状态:_STATE,确认:_CONFIRM,弹框:_ALERT,对话框:_DIALOG,赋值:_ASSIGN,通知:_MESSAGE,成功:_SUCCESS,失败:_FAILURE,
// 结账:_CHECKOUT,清除:_CLEAR,重置:_RESET,可用、允许:_ABLE,
// 列表:_LIST,文件:_FILE,任意类型:_ARBIT,数字:_NUMBER,对象:_OBJECT,布尔:_BOOLEAN,日期:_DATE,
// 标记id:_ID,信息:_INFO,编号:_NO,概率:_RATE,约束:_CONSTRAINT,匹配:_MATCH,

约束-前缀

// 接收:RECEIVE_,请求:REQUEST_,添加:ADD_TO_,是否:IS_,有无:HAS_,移除:RM_,删除:DEL_,重新:RE_,更新:UPDATE_,

actions

采用驼峰命名,以功能性词汇开头。

 getWords (context) { // 请求获取works
}
setStateWords (context) {
// 设置
}

modules

采用驼峰命名,注意模块划分。

modules: {
    common: {
      namespaced: true, // 根据模块注册的路径调整命名
      modules: {
        wordsStore
      }
    },
    pictureBooks
  }

分离

结构、样式、行为分离,尽量确保文档和模板只包含 HTML 结构,样式都放到样式表里,行为都放到脚本里。
功能应用分离:方法该做的事叫给方法做,不要为了便利直接为对象的某个变量进行运算赋值。

统一注释

HTML 模块注释:

<!-- 文章列表列表模块 -->
<div class="article-list">
...
</div>

HTML 区块注释:

<!--
@name: Drop Down Menu
@description: Style of top bar drop down menu.
@author: Ashu(Aaaaaashu@gmail.com)
-->

JS 单行注释:
在代码上面注释,必须独占一行。// 后跟一个空格,缩进与下一行被注释说明的代码一致。

JS 后缀注释:
在一段语句后面后缀进行注释, // 前后都跟一个空格,用于对某个语句的说明。

this.getBaseDataAfter() // 基础数据请求完成之后执行的方法

JS 多行注释

/**
 * 函数描述
 * 与此函数相关联引入的其他函数,并说明该函数具体位置以及说明其功能
 * @param {string} p1 参数1的说明
 * @param {string} p2 参数2的说明,比较长
 *     那就换行了.
 * @param {number=} p3 参数3的说明(可选)
 * @return {Object} 返回值描述
 */

JS 文件注释
文件注释用于告诉不熟悉这段代码的读者这个文件中包含哪些东西。 应该提供文件的大体内容, 它的作者, 依赖关系和兼容性信息。如下:

/**
 * @fileoverview Description of file, its uses and information
 * about its dependencies.
 * @author user@meizu.com (Firstname Lastname)
 * Copyright 2015 Meizu Inc. All Rights Reserved.
 */

多进行注释,对于自行定义的一些对象参数必须进行注释说明如下:

{
          name: null, // 姓名
          mobile: null, // 手机号码
          id_card: null, // 身份证号
          monthly_income_money: '', // 月收入
}

语义化和命名

应以功能或内容命名,不以表现形式命名;命名-缩写规范使用业界熟知的或者约定俗成的。常量采用全部大写,单词间下划线分隔的命名方式。变量采用驼峰命名法。全局属性或者引入文件采用$驼峰命名法进行命名。私有属性、变量和方法以下划线 _ 开头。由多个单词组成的 缩写词,在命名中,根据当前命名法和出现的位置,所有字母的大小写与首字母的大小写保持一致。枚举变量 使用 Pascal 命名法。(与骆驼命名法类似。只不过骆驼命名法是首字母小写,而帕斯卡命名法是首字母大写)

var HTML_ENTITY = {}; // 常量
var loadingModules = {}; // 变量
var _privateMethod = {}; // 私有属性、变量和方法
function XMLParser() {}; // 多个单词组成的 缩写词
import CustomUnit from './config/unit.js' // 枚举变量

命名-缩写规范:

navigation   =>  nav
header       =>  hd
description  =>  desc
button => btn
previous => prev

css 命名

ID、Class :采用命名必须由单词、中划线-连接或数字组成命名。不允许使用拼音(约定俗成的除外,如:youku, baidu),尤其是缩写的拼音、拼音与英文的混合。

命名-前缀规范:

选择器必须是以某个前缀开头

.m-detail .info { sRules; }
.m-detail .current { sRules; }
.m-detail .news { sRules; }
前缀 说明 示例
g- 全局通用样式命名,前缀g全称为global,一旦修改将影响全站样式 g-mod
m- 模块命名方式 m-detail
ui- 组件命名方式 ui-selector
js- 所有用于纯交互的命名,不涉及任何样式规则。JSer拥有全部定义权限 js-switch

出于性能考量,在没有必要的情况下避免元素选择器叠加 Class、ID 使用。

JS 命名

对于不经常使用jquery的项目,在使用jquery的地方必须进行jquery的标注声明:

/* global $ */

JS 对象或JSON的属性命名:字母小写,多个单词组成时,采用下划线分隔。

var obj = {
    result_type: '',
    name: '',
    status_show: ''
}

JS 函数命名:使用动宾短语和驼峰命名法,参数也使用驼峰命名法,可选参数以 opt_ 开头.

function getStyle(element, opt_child) {}

JS 类:使用名词和Pascal 命名法(与骆驼命名法类似。只不过骆驼命名法是首字母小写,而帕斯卡命名法是首字母大写),类的 方法 / 属性, 使用驼峰命名法。

function Engine(options) {}

boolean 类型的变量使用 is 或 has 开头。如果在对象中使用is_has_开头

var isReady = false;
var hasMoreCommands = false;
var obj = {
    is_show: false,
    has_name: true
}

JS 组件命名:文件名和组件名采用中划线-连接命名

date-range.js // 日期范围选择
<!-- 视频自定义播放组件 -->
<video-play></video-play>

操作符始终写在前一行, 以免分号的隐式插入产生预想不到的问题。

var y = a ?
    longButSimpleOperandB : longButSimpleOperandC;
if (a === 'string' ||
    s === 'object'
) {}

接口命名规范:可读性强,见名晓义;尽量不与各个社区已有的习惯冲突;尽量写全。不用缩写,除非是下面列表中约定的;(变量以表达清楚为目标,uglify 会完成压缩体积工作)

常用后缀:

_id-标记id
_form-表单
_name-标记_id对应的结果/名称
_photo-标记图片
_pdf-PDF文件
_video-视频
_audio-音频
_excel-表格
_number-数字
_date-日期
_info-信息
_rate-概率
_serialnum-编号/_NO-编号
_abel-是否可以Boolean
_remarks-备注
_result-结果
_loading-加载
_alert-弹框
_assign-赋值
_reset-重置
_able-允许
_state-状态
_confirm-确认
_dialog-对话框
_msg-通知
_succ-成功
_err-错误
_failure-失败
_clear-清除
_lists-列表
_file-文件
_infor-信息
_rate-概率

常用前缀:

is_: 是、可以/否、不可以Boolean
show_: 显示/隐藏Boolean
has_: 有/无Boolean
re_: 重新/再一次
add_to_添加
rm_: 移除
del_: 删除
update_: 更新
up_: 上
down_: 下
req_: 请求
resp_: 响应
receive_: 接收
dis_: 禁止
pre_: 预
sub_: 低、下
co_: 共同、和
ec_: 超出
auto_: 自动
inter_: 之间
mono_: 单独、单一
bith_: 两个、二
tri_: 三
mutil_: 多个
se_: 分离
aph_: 来自
trans_: 通过
pub_: 公共
into_: 输入
intro_: 到...中
all_: 全部

HTML HEAD 模板

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Style Guide</title>
    <meta name="description" content="不超过150个字符">
    <meta name="keywords" content="">
    <meta name="author" content="name, email@gmail.com">

    <!-- 为移动设备添加 viewport -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- iOS 图标 -->
    <link rel="apple-touch-icon-precomposed" href="//www.greatytc.com/apple-touch-icon-57x57-precomposed.png">

    <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
    <link rel="shortcut icon" href="path/to/favicon.ico">
</head>

声明顺序

css声明顺序

相关属性应为一组,推荐的样式编写顺序

  1. Positioning(定位)
  2. Box model(盒子模型)
  3. Typographic(排版)
  4. Visual(视觉效果,如动画颜色等)
  5. other(其他)
/* Positioning */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 100;

  /* Box model */
  display: block;
  box-sizing: border-box;
  width: 100px;
  height: 100px;
  padding: 10px;
  border: 1px solid #e5e5e5;
  border-radius: 3px;
  margin: 10px;
  float: right;
  overflow: hidden;

  /* Typographic */
  font: normal 13px "Helvetica Neue", sans-serif;
  line-height: 1.5;
  text-align: center;

  /* Visual */
  background-color: #f5f5f5;
  color: #fff;
  opacity: .8;

  /* Other */
  cursor: pointer;

结构以ESLint为准

比如缩进,=的前后有空格等都按ESLint为准

JS语言特性

[强制] 任何使用this的地方都要说名此this代表谁。

[强制] 每个 var 只能声明一个变量。一个 var 声明多个变量,容易导致较长的行长度,并且在修改时容易造成逗号和分号的混淆。

var hangModules = [];
var missModules = [];
var visited = {};

[强制] 变量必须 即用即声明,不得在函数或其它形式的代码块起始位置统一声明所有变量。变量声明与使用的距离越远,出现的跨度越大,代码的阅读与维护成本越高。

[强制] 在 判断中使用类型严格的 ===。

[建议] 按执行频率排列判断或代码分支的顺序。

[建议] 如果函数或全局中的 else 块后没有任何语句,可以删除 else。

function getName() {
    if (name) {
        return name;
    }

    return 'unnamed';
}

[建议] 不要在循环体中包含函数表达式,事先将函数提取到循环体外。因为循环体中的函数表达式,运行过程中会生成循环次数个函数对象。

function clicker() {
    // ......
}
for (var i = 0, len = elements.length; i < len; i++) {
    var element = elements[i];
    addListener(element, "click", clicker);
}

[建议] 对循环内多次使用的不变值,在循环外用变量缓存。

var width = wrap.offsetWidth + 'px';
for (var i = 0, len = elements.length; i < len; i++) {
    var element = elements[i];
    element.style.width = width;
    // ......
}

[建议] 类型检测优先使用 typeof。对象类型检测使用 instanceof。null 或 undefined 的检测使用 == null。

// string
typeof variable === 'string'

// number
typeof variable === 'number'

// boolean
typeof variable === 'boolean'

// Function
typeof variable === 'function'

// Object
typeof variable === 'object'

// RegExp
variable instanceof RegExp

// Array
variable instanceof Array

// null
variable === null

// null or undefined
variable == null

// undefined
typeof variable === 'undefined'

[强制] 字符串开头和结束使用单引号 '。输入单引号不需要按住 shift,方便输入。实际使用中,字符串经常用来拼接 HTML。为方便 HTML 中包含双引号而不需要转义写法。

[强制] 不允许修改和扩展任何原生对象和宿主对象的原型。

[建议] 属性访问时,尽量使用 .。

[建议] 一个函数的长度控制在 50 行以内。将过多的逻辑单元混在一个大函数中,易导致难以维护。一个清晰易懂的函数应该完成单一的逻辑单元。复杂的操作应进一步抽取,通过函数的调用来体现流程。特定算法等不可分割的逻辑允许例外。

function syncViewStateOnUserAction() {
    if (x.checked) {
        y.checked = true;
        z.value = '';
    }
    else {
        y.checked = false;
    }

    if (a.value) {
        warning.innerText = '';
        submitButton.disabled = false;
    }
    else {
        warning.innerText = 'Please enter it';
        submitButton.disabled = true;
    }
}

// 直接阅读该函数会难以明确其主线逻辑,因此下方是一种更合理的表达方式:

function syncViewStateOnUserAction() {
    syncXStateToView();
    checkAAvailability();
}

function syncXStateToView() {
    y.checked = x.checked;

    if (x.checked) {
        z.value = '';
    }
}

function checkAAvailability() {
    if (a.value) {
        clearWarnignForA();
    }
    else {
        displayWarningForAMissing();
    }
}

[建议] 一个函数的参数控制在 6 个以内。

[建议] 属性在构造函数中声明,方法在原型中声明。

function TextNode(value, engine) {
    this.value = value;
    this.engine = engine;
}

TextNode.prototype.clone = function () {
    return this;
};

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • 基本准则 符合web标准,html语义化;html,css,JavaScript分离;代码简洁有序,尽可能减少冗余...
    喵呜君阅读 787评论 0 1
  • Web前端开发规范文档 规范目的: 使开发流程更加规范化。 通用规范: TAB键用两个空格代替(WINDOWS下T...
    荞叶阅读 544评论 0 1
  • 一.规范目的 使开发流程更加规范化。 二.通用规范 TAB键用两个空格代替(WINDOWS下TAB键占四个空格,L...
    overflow_hidden阅读 2,418评论 0 0
  • 越长大确实是越孤单。 等你长大以后就会明白的那种无奈和无力,因为有太多事是你尽力也不能够做好的。会失去和朋友在一起...
    青祝芳华阅读 291评论 0 0
  • 本科的时候,我很肆意。在东大,我却很小心谨慎,因为没有归属感。没有那种我犯了错,也会被包容的感觉。你知道,它不会包...
    e8e976845a84阅读 403评论 2 2