命名规范
项目命名
采用小写驼峰命名
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
=
{
: {
value
:
1
,
desc
:
登录
‘
},
: {
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
?
版权声明:本文为z1093541823原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。