前端开发技术规范

  • Post author:
  • Post category:其他




命名规范



项目命名


采用小写驼峰命名


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


?



版权声明:本文为z1093541823原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。