前端开发技术规范

命名规范
项目命名
采用小写驼峰命名 lowerCamelCase ,代码中的命名均不能以下划线,也不能以下划线或美元符号结
束;
目录命名
全部采用小写驼峰命名 lowerCamelCase ,有复数结构时,要采用复数命名法, 缩写不用复数。
JS CSS HTML PNG 文件命名
采用小写驼峰命名 lowerCamelCase ,代码中的命名均不能以下划线,也不能以下划线或美元符号结
束;
命名严谨性
1 、代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。 说明:正确的英文
拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式也要避免采用;
// good
mallManagementSystem
// bad
mall_management-system / mall-management-system
// good
scripts / styles / components / images / utils / layouts / demoStyles /
demoScripts / img / doc
// bad
script / style / demo_scripts / demo-styles / imgs / docs
// good
renderDom.js / signup.css / index.html / companyLogo.png
// bad
render-dom.js / UserManagement.html
// good
henan / luoyang / rmb 等国际通用的名称,可视同英文。
// bad
DaZhePromotion [ 打折 ] / getPingfenByName() [ 评分 ] / int 某变量 = 3 2 、杜绝完全不规范的缩写,避免望文不知义。
HTML 规范
HTML 标签
标签必须合法且闭合、嵌套正确,标签名需 小写
标签语法无错误,需要符合语义化;
标签的自定义属性以 data - 开头,如: <a href="#" data - num='18'></a>
除非有特定的功能、组件要求等,禁止随意使用 id 来定义元素样式。
链接
<a> 标签加上 title 属性;
<a> 标签的 href 属性必须写上链接地址,暂无的加上 javascript:alert(' 敬请期待! ')
非本专题的页面间跳转,采用打开新窗口模式: target="_blank"
HTML 类型
推荐使用 HTML5 的文档类型申明:(建议使用 text/html 格式的 HTML 。避免使用 XHTML XHTML
以及它的属性,比如 application/xhtml+xml 在浏览器中的应用支持与优化空间都十分有限)。
缩进
缩进使用 2 个空格(一个 Tab );
嵌套的节点应该缩进。
语义化标签
// bad
AbstractClass“ 缩写 命名成 AbsClass
condition“ 缩写 命名成 condi ,此类随意缩写严重降低了代码的可阅读性。
规定字符编码
IE 兼容模式
规定字符编码
doctype 大写
// good
<!DOCTYPE html>
<html>
<head>
<meta http-equiv = "X-UA-Compatible" content = "IE=Edge" />
<meta charset = "UTF-8" />
<title> Page title </title>
</head>
<body>
<img src = "images/company-logo.png" alt = "Company" />
</body>
</html> HTML5 中新增很多语义化标签,所以优先使用语义化标签,避免一个页面都是 div 或者 p 标签。
引号 (html vue template 模板 )
使用双引号 (" ") 而不是单引号 ('')
CSS 规范
命名
ID class 的名称总是使用可以反应元素目的和用途的名称,或其他通用的名称,代替表象和晦涩难懂
的名称。
属性书写顺序
建议遵循以下顺序:
布局定位属性: display / position / float / clear / visibility / overflow
// good
<header></header>
<footer></footer>
// bad
<div>
<p></p>
</div>
类名使用小写字母,以中划线分隔
id 采用驼峰式命名
scss less 中的变量、函数、混合、 placeholder 采用驼峰式命名
// bad
.fw-800 {
font-weight : 800 ;
}
.red {
color : red ;
}
// good
.heavy {
font-weight : 800 ;
}
.important {
color : red ;
} 自身属性: width / height / margin / padding / border / background
文本属性: color / font / text-decoration / text-align / vertical-align / white- space / break-word
其他属性( CSS3 ): content / cursor / border-radius / box-shadow / text-shadow /
background:linear-gradient …
选择器
css 选择器中避免使用标签名,从结构、表现、行为分离的原则来看,应该尽量避免 css 中出现 HTML
标签,并且在 css 选择器中出现标签名会存在潜在的问题。
很多前端开发人员写选择器链的时候不使用 直接子选择器(注:直接子选择器和后代选择器的区别)。
有时,这可能会导致疼痛的设计问题并且有时候可能会很耗性能。然而,在任何情况下,这是一个非常
不好的做法。如果你不写很通用的,需要匹配到 DOM 末端的选择器, 你应该总是考虑直接子选择器。
尽量使用缩写属性
.about {
display : block ;
position : relative ;
float : left ;
over-flow : auto ;
width : 100px ;
height : 100px ;
margin : 0 10px ;
padding : 20px 0 ;
background : rgba ( 0 , 0 , 0 , .5 );
border : 1px solid red ;
color : #333 ;
font-family : Arial , 'Helvetica Neue' , Helvetica , sans-serif ;
text-align : center ;
cursor : pointer ;
border-radius : 10px ;
}
// good
.content > .title {
font-size : 2rem ;
}
// bad
.content .title {
font-size : 2rem ;
}
// good
border-top : 0 ;
font : 100% / 1.6 palatino , georgia , serif ;
padding : 0 1em 2em ;
// bad
border-top-style : none ; 每个选择器及属性独占一行
省略 0 后面的单位
避免使用 ID 选择器及全局标签选择器防止污染全局样式
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
button {
width : 100px ;
height : 50px ;
color : #fff ;
background : #00a0e9 ;
}
// bad
button {
width : 100px ; height : 50px ; color : #fff ; background : #00a0e9 ;
}
// good
div {
padding-bottom : 0 ;
margin : 0 ;
}
// bad
div {
padding-bottom : 0px ;
margin : 0em ;
} CSS3 浏览器私有前缀写法
CSS3 浏览器私有前缀在前,标准前缀在后。
Javascript 规范
命名
1 、采用小写驼峰命名 lowerCamelCase ,代码中的命名均不能以下划线,也不能以下划线或美元符号结
束;
2 、其中 method 方法命名必须是 动词 或者 动词 + 名词 形式;
// good
.header {
padding-bottom : 0px ;
margin : 0em ;
}
// bad
#header {
padding-bottom : 0px ;
margin : 0em ;
}
.about {
border-radius : 10px ;
-webkit- border-radius : 10px ;
-moz- border-radius : 10px ;
-o- border-radius : 10px ;
-ms- border-radius : 10px ;
}
// good
localValue / getHttpMessage () / inputUserId
// bad
_name / name_ / name$ 2 ) 方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase
格,必须遵从驼峰形式。
// good
saveShopCarData / openShopCarInfoDialog
// bad
save / open / show / go 3 、特此说明,增删查改,详情统一使用如下 5 个单词,不得使用其他(目的是为了统一各个端) ;
`add / update / delete / detail / get`
附: 函数方法常用的动词 :
/**
get 获取 /set 设置
add 增加 /remove 删除
create 创建 /destory 移除
start 启动 /stop 停止
open 打开 /close 关闭
read 读取 /write 写入
load 载入 /save 保存
create 创建 /destroy 销毁
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 解锁
check out 签出 /check in 签入
submit 提交 /commit 交付
push /pull
expand 展开 /collapse 折叠
begin 起始 /end 结束
start 开始 /finish 完成 4 、常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
代码格式
1 、使用 2 个空格进行缩进 ;
2 、不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。
说明:任何情形,没有必要插入多个空行进行隔开。
字符串
统一使用单引号 ('') ,不使用双引号 ("") 。这在创建 HTML 字符串非常有好处:
对象声明
1 、使用字面值创建对象 ;
enter 进入 /exit 退出
abort 放弃 /quit 离开
obsolete 废弃 /depreciate 废旧
collect 收集 /aggregate 聚集
**/
// good
const MAX_STOCK_COUNT
// bad
const MAX_COUNT
// good
if ( x < y ) {
x += 10 ;
} else {
x += 1 ;
}
// good
let str = 'foo' ;
let testDiv = '<div id="test"></div>' ;
// bad
let str = 'foo' ;
let testDiv = "<div id='test'></div>" ; 2 、使用字面量来代替对象构造器。
括号
下列关键字后必须有大括号(即使代码块的内容只有一行):
条件判断和循环最多三层
条件判断能使用三目运算符和逻辑运算符解决的,就不要使用条件判断,但是谨记不要写太长的三目运
算符。如果超过 3 层请抽成函数,并写清楚注释。
this 的转换命名
对上下文 this 的引用只能使用 'that' 来命名
块级作用域
1 let 取代 var;
// good
let user = {};
// bad
let user = new Object ();
// good
var user = {
age : 0 ,
name : 1 ,
city : 3
};
// bad
var user = new Object ();
user . age = 0 ;
user . name = 0 ;
user . city = 0 ;
if , else , for , while , do , switch , try , catch , finally , with
// good
if ( condition ) {
doSomething ();
}
// if 后单行内容时
condition && doSomething ()
// bad
if ( condition ) doSomething (); ES6 提出了两个新的声明变量的命令: let const 。其中, let 完全可以取代 var ,因为两者语义相同,
而且 let 没有副作用。
所以,建议不再使用 var 命令,而是使用 let 命令取代。
2 、全局常量和线程安全。
let const 之间,建议优先使用 const ,尤其是在全局环境,不应该设置变量,只应设置常量。
const 优于 let 有几个原因。一个是 const 可以提醒阅读程序的人,这个变量不应该改变;另一个是
const 比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;
最后一个原因是 JavaScript 编译器会对 const 进行优化,所以多使用 const ,有利于提高程序的运行效
率,也就是说 let const 的本质区别,其实是编译器内部的处理不同。
const 声明常量还有两个好处,一是阅读代码的人立刻会意识到不应该修改这个值,二是防止了无意间
修改变量值所导致的错误。
所有的函数都应该设置为常量。
字符串
静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。
解构赋值
1 、使用数组成员对变量赋值时,优先使用解构赋值;
2 、函数的参数如果是对象的成员,优先使用解构赋值;
// bad
const a = "foobar" ;
const b = 'foo' + a + 'bar' ;
// acceptable
const c = `foobar` ;
// good
const a = 'foobar' ;
const b = `foo${ a }bar` ;
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 ; 3 、如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值。这样便于以后添加返回
值,以及更改返回值的顺序。
对象
1 、单行定义的对象,最后一个成员不以逗号结尾。多行定义的对象,最后一个成员以逗号结尾;
}
// good
function getFullName ( obj ) {
const {
firstName ,
lastName
} = obj ;
}
// best
function getFullName ({
firstName ,
lastName
}) {}
// bad
function processInput ( input ) {
return [ left , right , top , bottom ];
}
// good
function processInput ( input ) {
return {
left ,
right ,
top ,
bottom
};
}
const {
left ,
right
} = processInput ( input );
// bad
const a = { k1 : v1 , k2 : v2 , };
const b = {
k1 : v1 ,
k2 : v2
};
// good
const a = { k1 : v1 , k2 : v2 }; const b = {
k1 : v1 ,
k2 : v2 ,
};
2 、对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用
Object.assign 方法;
// bad
const a = {};
a . x = 3 ;
// if reshape unavoidable
const a = {};
Object . assign ( a , { x : 3 });
// good
const a = { x : null };
a . x = 3 ;
3 、如果对象的属性名是动态的,可以在创造对象的时候,使用属性表达式定义;
// bad
const obj = {
id : 5 ,
name : 'San Francisco' ,
};
obj [ getKey ( 'enabled' )] = true ;
// good
const obj = {
id : 5 ,
name : 'San Francisco' ,
[ getKey ( 'enabled' )]: true ,
};
4 、另外,对象的属性和方法,尽量采用简洁表达法,这样易于描述和书写。
var ref = 'some value' ;
// bad
const atom = {
ref : ref ,
value : 1 ,
addValue : function ( value ) {
return atom . value + value ;
},
};
// good
const atom = { 数组
1 、使用扩展运算符( ... )拷贝数组;
2 、使用 Array.from 方法,将类似数组的对象转为数组。
函数
1 、立即执行函数可以写成箭头函数的形式;
2 、那些使用匿名函数当作参数的场合,尽量用箭头函数代替。因为这样更简洁,而且绑定了 this
ref ,
value : 1 ,
addValue ( value ) {
return atom . value + value ;
},
};
// bad
const len = items . length ;
const itemsCopy = [];
let i ;
for ( i = 0 ; i < len ; i ++ ) {
itemsCopy [ i ] = items [ i ];
}
// good
const itemsCopy = [ ... items ];
const foo = document . querySelectorAll ( '.foo' );
const nodes = Array . from ( foo );
//Array.from 与扩展运算符的区别
Array . from 方法还支持类似数组的对象。所谓类似数组的对象,本质特征只有一点,即必须有 length 属性。
因此,任何有 length 属性的对象,都可以通过 Array . from 方法转为数组,而此时扩展运算符就无法转换。
Array . from ({ length : 3 });
// [ undefined, undefined, undefined ]
上面代码中, Array . from 返回了一个具有三个成员的数组,每个位置的值都是 undefined 。扩展运算符转换
不了这个对象。
(() => {
console . log ( 'Welcome to the Internet.' );
})(); // bad
[ 1 , 2 , 3 ]. map ( function ( x ) {
return x * x ;
});
// good
[ 1 , 2 , 3 ]. map (( x ) => {
return x * x ;
});
// best
[ 1 , 2 , 3 ]. map ( x => x * x );
3 、箭头函数取代 Function.prototype.bind ,不应再用 self/_this/that 绑定 this
// 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 );
4 、简单的、单行的、不会复用的函数,建议采用箭头函数。如果函数体较为复杂,行数较多,还是应该
采用传统的函数写法;
5 、所有配置项都应该集中在一个对象,放在最后一个参数,布尔值不可以直接作为参数;
// bad
function divide ( a , b , option = false ) {}
// good
function divide ( a , b , {
option = false
} = {}) {}
6 、不要在函数体内使用 arguments 变量,使用 rest 运算符( ... )代替。因为 rest 运算符显式表明你想
要获取参数,而且 arguments 是一个类似数组的对象,而 rest 运算符可以提供一个真正的数组; 7 、使用默认值语法设置函数参数的默认值。
Map 解构
注意区分 Object Map ,只有模拟现实世界的实体对象时,才使用 Object 。如果只是需要 key: value
的数据结构,使用 Map 结构。因为 Map 有内建的遍历机制。
模块
ES6 模块语法是 JavaScript 模块的标准写法,坚持使用这种写法,取代 Node.js CommonJS
法。
1 、使用 import 取代 require()
// bad
function concatenateAll () {
const args = Array . prototype . slice . call ( arguments );
return args . join ( '' );
}
// good
function concatenateAll ( ... args ) {
return args . join ( '' );
}
// bad
function handleThings ( opts ) {
opts = opts || {};
}
// good
function handleThings ( opts = {}) {
// ...
}
let map = new Map ( arr );
for ( let key of map . keys ()) {
console . log ( key );
}
for ( let value of map . values ()) {
console . log ( value );
}
for ( let item of map . entries ()) {
console . log ( item [ 0 ], item [ 1 ]);
} // CommonJS 的写法
const moduleA = require ( 'moduleA' );
const func1 = moduleA . func1 ;
const func2 = moduleA . func2 ;
// ES6 的写法
import { func1 , func2 } from 'moduleA' ;
2 、使用 export 取代 module.exports
// commonJS 的写法
var React = require ( 'react' );
var Breadcrumbs = React . createClass ({
render () {
return < nav / > ;
}
});
module . exports = Breadcrumbs ;
// ES6 的写法
import React from 'react' ;
class Breadcrumbs extends React . Component {
render () {
return < nav / > ;
}
};
export default Breadcrumbs ;
如果模块只有一个输出值,就使用 export default ,如果模块有多个输出值,除非其中某个输出值特别
重要,否则建议不要使用 export default ,即多个输出值如果是平等关系, export default 与普通的
export 就不要同时使用。
3 、如果模块默认输出一个函数,函数名的首字母应该小写,表示这是一个工具方法;
function makeStyleGuide () {}
export default makeStyleGuide ;
4 、如果模块默认输出一个对象,对象名的首字母应该大写,表示这是一个配置值对象。
const StyleGuide = {
es6 : {}
};
export default StyleGuide ; Vue 书写规范
组件引入顺序
引入组件时,应遵循从全局到局部,从 vue js 的顺序引入
组件名为多个单词
组件名应该始终由多个单词组成,除了根组件 App ,以及 <transition> <component> 之类的
Vue 内置组件。
这样做可以避免与现有以及未来的 HTML 元素 产生冲突 ,因为所有的 HTML 元素名称都是单个单词的。
组件文件
只要有能够拼接文件的构建系统,就把每个组件单独分成文件。
当你需要编辑一个组件,或查阅一个组件的用法时,这种做法可以帮助你更快速地找到它。
<script>
import { mapGetters } from 'vuex' ;
import eventBus from '../event/eventBus.js'
import TodoLtem from '@/component/todoList.vue' // 这个组件是待办列表 // 引入 vue 文件
时,必须携带 .vue 后缀
import {
getUserInfo , // 获取用户基本信息
getUserLoginInfo // 获取登录用户详细信息
} from '@/api/common/userInfo.js'
</script>
// good
app . component ( 'todo-item' , {
// ...
})
export default {
name : 'TodoItem' ,
// ...
}
// bad
app . component ( 'todo' , {
// ...
})
export default {
name : 'TodoItem' ,
// ...
} 单文件组件文件的大小写
单文件组件的文件名应该采用小驼峰命名法 lowerCamelCase ,代码中的命名均不能以下划线、中划线
连接
单文件组件的 name 应采用大驼峰命名法 UpperCamelCase , 在组件注册时应采用大驼峰命名,组件在
模板中使用时亦采用大驼峰命名
// good
components /
|- TodoList . vue
|- TodoItem . vue
// bad
app . component ( 'TodoList' , {
// ...
})
app . component ( 'TodoItem' , {
// ...
})
// good
components /
|- myComponent . vue
// bad
components /
|- my - component . vue
//good
export default {
name : 'MyComponent'
}
<template>
<MyComponent> </MyComponent>
</template>
<script>
import MyComponent from './myComponent.vue'
export default {
component :{
MyComponent
}
}
</script> 基础组件名称
应用特定样式和约定的基础组件 ( 也就是展示类的、无逻辑的或无状态的组件 ) 应该全部以一个特定的前
缀开头,比如 Base App V
紧密耦合的组件名称
与父组件紧密耦合的子组件应该以父组件名作为前缀命名。
如果特性元素较多,应该主动换行
// good
components /
|- BaseButton . vue
|- BaseTable . vue
|- BaseIcon . vue
components /
|- AppButton . vue
|- AppTable . vue
|- AppIcon . vue
components /
|- VButton . vue
|- VTable . vue
|- VIcon . vue
// bad
components /
|- MyButton . vue
|- VueTable . vue
|- Icon . vue
// good
components /
|- todoList . vue
|- todoListItem . vue
|- todoListItemButton . vue
// bad
components /
|- TodoList . vue
|- TodoItem . vue
|- TodoButton . vue
// good
<MyComponent
foo = "a"
bar = "b"
baz = "c"
foo = "a" Prop 定义
Prop 定义应尽量详细
在提交的代码中, prop 的定义应该尽量详细,至少指定其类型。
细致的 prop 定义 有两个优势:
它们写明了组件的 API ,所以组件的设计用法可以通俗易懂;
在开发环境下,如果为一个组件提供了格式不正确的 prop Vue 将会告警,以帮助你捕获潜在的
错误来源。
v - for 设置 key
始终以 key 配合 v - for
bar = "b"
baz = "c"
foo = "a"
bar = "b"
baz = "c"
/>
// bad
<MyComponent foo = "a" bar = "b" baz = "c" foo = "a" bar = "b" baz = "c" foo = "a" bar = "b"
baz = "c" foo = "a" bar = "b" baz = "c" />
// good
props : {
status : String
}
// 更好的例子
props : {
status : {
type : String ,
required : true ,
validator : value => {
return [
'syncing' ,
'synced' ,
'version-conflict' ,
'error'
]. includes ( value )
}
}
}
// bad
// 只有在原型开发时,这么做才能被接受
props : [ 'status' ] 在组件上必须始终以 key 配合 v - for ,以便维护内部组件及其子树的状态。即使对于元素,维持可预
测的行为也是一种好的做法。禁止使用循环的 index 作为组件的 key
避免 v - if v - for 一起使用 (vue2.x)
永远不要在一个元素上同时使用 v - if v - for
一般我们在两种常见的情况下会倾向于这样做:
为了对列表中的项目进行过滤 ( 比如 v - for="user in users" v - if="user.isActive" ) 。在这种
情形下,请将 users 替换为一个计算属性 ( 比如 activeUsers ) ,返回过滤后的列表。
为了避免渲染本应该被隐藏的列表 ( 比如 v - for="user in users" v - if="shouldShowUsers" )
这种情形下,请将 v - if 移动至容器元素上 ( 比如 ul ol )
// 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>
< ul >
< li v - for = "(todo,idx) in todos" : key = "idx" >
{ { todo . text }}
< /li>
< /ul>
// good
<ul>
<template v-for = "user in users" :key = "user.id" >
<li v-if = "user.isActive" >
{ { user.name }}
</li>
</template>
</ul>
// bad
<ul>
<li
v-for = "user in users"
v-if = "user.isActive"
:key = "user.id"
>
{ { user.name }} 为组件样式设置作用域
对于应用来说,样式在顶层 App 组件和布局组件中可以是全局的,但是在其它所有组件中都应该是有
作用域的。
这条规则只适用于 单文件组件 。你 不一定 要使用 scoped attribute 。作用域也可以通过 CSS Modules
( 一个基于 class 的,类似 BEM 的策略 ) 或者其它的库 / 约定来实现。
不管怎样,对于组件库来说,我们应该更倾向于选用基于 class 的策略,而不是 scoped attribute
这会让覆写内部样式变得更容易:使用人类可理解的 class 名称,没有太高的选择器优先级,而且不太
会导致冲突。
模板中使用简单的表达式
组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。
</li>
</ul>
// good
<template>
<button class = "button button-close" > × </button>
</template>
<!-- 使用 `scoped` attribute -->
<style scoped >
.button {
border : none ;
border-radius : 2px ;
}
.button-close {
background-color : red ;
}
</style>
// bad
<template>
<button class = "btn btn-close" > × </button>
</template>
<style>
.btn-close {
background-color : red ;
}
</style>
// good
<template>
<p> { { normalizedFullName }} </p> 指令缩写
指令缩写 ( : 表示 v - bind: @ 表示 v - on: 和用 # 表示 v - slot ) 应该要么始终使用,要么始终不
使用。
</template>
// 复杂表达式已经移入一个计算属性
computed: {
normalizedFullName: function () {
return this.fullName.split(' ').map(function (word) {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}
}
// bad
<template>
<p>
{ { fullName.split(' ').map(function (word) { return word[0].toUpperCase() +
word.slice(1) }).join(' ') }}
</p>
</template>
// good
<input
:value = "newTodoText"
:placeholder = "newTodoInstructions"
>
<input
v-bind:value = "newTodoText"
v-bind:placeholder = "newTodoInstructions"
>
<input
@input = "onInput"
@focus = "onFocus"
>
<input
v-on:input = "onInput"
v-on:focus = "onFocus"
>
<template v-slot:header >
<h1> Here might be a page title </h1>
</template>
<template v-slot:footer >
<p> Here's some contact info </p>
</template> 标签顺序保持一致
单文件组件应该总是让标签顺序保持为
v-show v-if 选择
如果运行时,需要非常频繁地切换,使用 v-show ;如果在运行时,条件很少改变,使用 v-if
组件 / 实例选项的顺序
组件 / 实例的选项应该有统一的顺序。
<template #header >
<h1> Here might be a page title </h1>
</template>
<template #footer >
<p> Here's some contact info </p>
</template>
// bad
<input
v-bind:value = "newTodoText"
:placeholder = "newTodoInstructions"
>
<input
v-on:input = "onInput"
@focus = "onFocus"
>
<template v-slot:header >
<h1> Here might be a page title </h1>
</template>
<template #footer >
<p> Here's some contact info </p>
</template>
// good
<template> ... </template>
<script> ... </script>
<style> ... </style>
// bad
<template> ... </template>
<style> ... </style>
<script> ... </script> 这是我们为组件选项推荐的默认顺序。它们被划分为几大类,你能够由此知道新的 property 应该被放到
哪里。
1. 全局感知 ( 要求在组件以外被感知 )
name
2. 模板编译选项 ( 改变模板编译的方式 )
compilerOptions
3. 模板依赖 ( 模板内使用的资源 )
components
directives
4. 组合 ( 合并 property 至选项内 )
extends
mixins
provide / inject
5. 接口 ( 组件的接口 )
inheritAttrs
props
emits
expose
6. 组合式 API ( 使用组合式 API 的入口点 )
setup
7. 本地状态 ( 本地的响应式 property)
data
computed
8. 事件 ( 通过响应式事件触发的回调 )
watch
生命周期事件 ( 按照它们被调用的顺序 )
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
activated
deactivated
beforeUnmount
unmounted
errorCaptured
renderTracked
renderTriggered
9. 非响应式的 property ( 不依赖响应性系统的实例 property)
methods
10. 渲染 ( 组件输出的声明式描述 )
template / render 元素 attribute 的顺序
元素 ( 包括组件 ) attribute 应该有统一的顺序。
这是我们为组件选项推荐的默认顺序。它们被划分为几大类,你能够由此知道新添加的自定义 attribute
和指令应该被放到哪里。
1. 定义 ( 提供组件的选项 )
is
2. 列表渲染 ( 创建相同元素的多个变体 )
v - for
3. 条件 ( 元素是否渲染 / 显示 )
v - if
v - else - if
v - else
v - show
v - cloak
4. 渲染修饰符 ( 改变元素的渲染方式 )
v - pre
v - once
5. 全局感知 ( 要求在组件以外被感知 )
id
6. 唯一性 Attribute ( 需要唯一值的 attribute)
ref
key
7. 双向绑定 ( 结合了绑定与事件 )
v - model
8. 其他 Attribute ( 所有普通的、绑定或未绑定的 attribute)
9. 事件 ( 组件事件监听器 )
v - on
10. 内容 ( 覆写元素的内容 )
v - html
v - text
scoped 中的元素选择器
元素选择器应该避免在 scoped 中出现。
scoped 样式中,类选择器要比元素选择器更好,因为大量地使用元素选择器是很慢的。
// good
<template>
<button class = "btn btn-close" > × </button>
</template>
<style scoped >
.btn-close {
background-color : red ; Vue Router 规范
页面跳转数据传递使用路由参数
使用路由懒加载(延迟加载)机制
router 中的命名规范
path childrenPoints 命名规范采用 小驼峰 命名规范(尽量 vue 文件的目录结构保持一致,因为目
录、文件名都是 小驼峰,这样很方便找到对应的文件)
**name 命名规范采用 大驼峰 命名规范且和 component 组件名保持一致!(因为要保持 keep-alive
特性, keep-alive 按照 component name 进行缓存,所以两者必须高度保持一致)
}
</style>
// bad
<template>
<button> × </button>
</template>
<style scoped >
button {
background-color : red ;
}
</style>
// good
let id = '123' ;
this . $router . push ({
name : 'userCenter' ,
query : {
id : id
}
});
// good
{
path : '/uploadAttachment' ,
name : 'UploadAttachment' ,
meta : {
title : ' 上传附件 '
},
component : () => import ( '@/view/components/uploadAttachment/index.vue' )
},
// 动态加载 Vue 项目目录规范
基础
vue 项目中的所有命名一定要与后端命名统一。比如权限:后端 privilege, 前端无论 router , store,
api 等都必须使用 privielege 单词!
目录说明
export const reload = [{
path : '/reload' ,
name : 'Reload' ,
component : Main ,
meta : {
title : ' 动态加载 ' ,
icon : 'icon iconfont'
},
children : [{
path : '/reload/smartReloadList' ,
name : 'SmartReloadList' ,
component : () =>
import ( '@/views/reload/smartReload/smartReloadList.vue' )
}]
}
];
src 源码目录
|-- api 所有 api 接口
|-- assets 静态资源, images, icons, styles
|-- components 公用组件
|-- config 配置信息
|-- constants 常量信息,项目所有 Enum, 全局常量等
|-- datas 模拟数据,临时存放
|-- mock 模拟接口,临时存放
|-- router 路由,统一管理
|-- store vuex, 统一管理
|-- themes 自定义样式主题
|-- views 视图目录
| |-- role role 模块名
| |-- |-- roleList.vue role 列表页面
| |-- |-- roleAdd.vue role 新建页面
| |-- |-- roleUpdate.vue role 更新页面
| |-- |-- index.less role 模块样式
| |-- |-- components role 模块通用组件文件夹
| |-- employee employee 模块 api 目录
assets 目录
components 目录
文件、变量命名要与后端保持一致。
此目录对应后端 API 接口,按照后端一个 controller 一个 api js 文件。若项目较大时,可以按
照业务划分子目录,并与后端保持一致。
api 中的方法名字要与后端 api url 尽量保持语义高度一致性。
对于 api 中的每个方法要添加注释,注释与后端 swagger 文档保持一致。
后端:
url EmployeeController.java
/employee/add
/employee/delete/{id}
/employee/update
前端:
employee.js
// 添加员工
addEmployee: (data) => {
return postAxios('/employee/add', data)
},
// 更新员工信息
updateEmployee: (data) => {
return postAxios('/employee/update', data)
},
// 删除员工
deleteEmployee: (employeeId) => {
return postAxios('/employee/delete/' + employeeId)
},
assets 为静态资源,里面存放 images, styles, icons 等静态资源,静态资源命名格式为
kebabCase
|assets
|-- icons
|-- images
| |-- backgroundColor.png
| |-- uploadHeader.png
|-- styles constants 目录
此目录应按照组件进行目录划分,目录命名为 kebabCase ,组件命名规则也为 kebabCase
|components
|-- errorLog
| |-- index.vue
| |-- index.less
|-- markdownEditor
| |-- index.vue
| |-- index.js
|-- kebabCase
此目录存放项目所有常量,如果常量在 vue 中使用,请使用 vue - enum 插件
( https : //www.npmjs.com/package/vue-enum)
目录结构:
| constants
|-- index . js
|-- role . js
|-- employee . js
例子: employee . js
export const EMPLOYEE_STATUS = {
NORMAL : {
value : 1 ,
desc : ' 正常 '
},
DISABLED : {
value : 1 ,
desc : ' 禁用 '
},
DELETED : {
value : 2 ,
desc : ' 已删除 '
}
};
export const EMPLOYEE_ACCOUNT_TYPE = {
QQ : {
value : 1 ,
desc : 'QQ 登录 '
},
WECHAT : {
value : 2 ,
desc : ' 微信登录 '
},
DINGDING : {
value : 3 ,
desc : ' 钉钉登录 '
}, router store 目录
views 目录
注释说明
注释要求
USERNAME : {
value : 4 ,
desc : ' 用户名密码登录 '
}
};
export default {
EMPLOYEE_STATUS ,
EMPLOYEE_ACCOUNT_TYPE
};
这两个目录一定要将业务进行拆分,不能放到一个 js 文件里。
router 尽量按照 views 中的结构保持一致。
store 建议按照业务进行拆分不同的 js 文件。当业务复杂时则必须拆分为不同模块
命名要与后端、 router api 等保持一致
components 中组件要使用 pascal-case 规则
|-- views 视图目录
| |-- role role 模块名
| | |-- roleList.vue role 列表页面
| | |-- roleAdd.vue role 新建页面
| | |-- roleUpdate.vue role 更新页面
| | |-- index.less role 模块样式
| | |-- components role 模块通用组件文件夹
| | | |-- roleHeader.vue role 头部组件
| | | |-- roleModal.vue role 弹出框组件
| |-- employee employee 模块
| |-- behaviorLog 行为日志 log 模块
| |-- codeGenerator 代码生成器模块 整理必须加注释的地方
其他
尽量不要手动操作 DOM
因使用 vue 框架,所以在项目开发中尽量使用 vue 的数据驱动更新 DOM ,尽量(不到万不得已)不要
手动操作 DOM ,包括:增删改 dom 元素、以及更改样式、添加事件等。
删除无用代码
因使用了 svn 代码版本工具,对于无用代码必须及时删除,例如:一些调试的 console 语句、
debugger 、无用的弃用功能代码。
svn 提交规范
注释
提交至 svn 代码库中的代码,每次 commit 需要填写本次提交所做出的修改,当有多个修改时使用有序列
表展示
代码完整性
提交至 svn 代码库中的代码,必须保证 Checkout 之后能正常运行, 禁止 控制台带着报错或警告信息就提
交代码,个人配置信息禁止上传至 svn 代码库以避免协同开发者出现冲突 , 代码中对于请求的 baseUrl 禁止
写死,多环境切换请使用 node 环境配置来决定使用哪个路径, 必须保证 代码库中的文件检出之后打包能
在各个环境下 正常运行
对于页面的注释在页面最上方需要写明以下内容()
<!--
des :关于这个页面的描述 需写明这个页面或组件的作用
creator : 创建人 (该文件最开始的编写人书写即可)
createTime : 创建时间(该文件最开始的编写人书写即可)
-->
对于页面因需求或 bug 需要修改的方法,也需要写明以下内容
/*
des :关于这个更改的描述 需写明这个更改的原因
updator : 创建人 (该修改的编写人 -- 不是当前文件的编制人才需要书写)
updateTime : 创建时间(该修改的编写人)
*/
公共组件使用说明
api 目录的接口 js 文件必须加注释写明该接口的作用
store 中的 state, mutation, action 等必须加注释写明该属性的作用
vue 文件在引入组件时,必须添加注释说明该组件用途
vue 文件在引入 api 中的方法时,必须添加注释说明该方法用途
vue 文件的 methods ,每个 method 必须添加注释,方法里复杂的业务处理必须额外添加注释
vue 文件的 data, 非常用属性名要加注释,例如: tableData/searchForm 不需要添加注释,
scaleEffectKey 需要添加注释
1.xxx
2.xxx ignore
//good
service . baseURL = process . env . VUE_APP_BASE_URL ;
//bad
service . baseURL = 'http://127.0.0.1:9999' ;
// 无需提交的各类型文件
. DS_Store
node_modules
/ dist
. history
# Log files
npm - debug . log *
yarn - debug . log *
yarn - error . log *
pnpm - debug . log *
# Editor directories and files
. idea
. vscode
* . suo
* . ntvs *
* . njsproj
* . sln
* . sw ?

猜你喜欢

转载自blog.csdn.net/z1093541823/article/details/125102169