前端团队有评审代码的要求,但因为每一个开发人员的水平不一样,技术关注点不一样,因此对代码评审的关注点不一样,为了保证代码质量,团队代码风格统一,特此拟定一份《前端团队代码评审 CheckList 清单》,这样代码评审人员在评审代码时,能够参照这份清单,对代码进行评审。从而辅助整个团队提升代码质量、统一代码规范。若是你的团队尚未这么一份代码评审 CheckList 清单,也许这正是你须要的;若是你的团队已经有了代码评审参照标准,这份清单也许能起到锦上添花的效果。javascript
辛苦整理良久,还望手动点赞鼓励~css
github地址为:github.com/fengshi123/…,若是喜欢或者有所启发,请帮忙给个 star ~,对做者也是一种鼓励。前端
eslint
检查的规范继承自 eslint-config-standard
检验规则,具体的规则介绍参照连接:cn.eslint.org/docs/rules/ ,这里及如下部分再也不重复介绍这些检验规则。
vue
stylelint
检查的规范继承自 stylelint-config-standard
检验规则,具体的规则介绍参照连接:www.npmjs.com/package/sty… ,这里及如下部分再也不重复介绍这些检验规则。
java
推荐:git
studentInfot复制代码
推荐:github
const Car = {
make: "Honda",
model: "Accord",
color: "Blue"
};复制代码
不推荐:vuex
const Car = {
carMake: "Honda",
carModel: "Accord",
carColor: "Blue"
};复制代码
推荐:
npm
.block__element{}
.block--modifier{}复制代码
命名须要符合语义化,若是函数命名,能够采用加上动词前缀:
编程
动词 | 含义 |
---|---|
can | 判断是否可执行某个动做 |
has | 判断是否含有某个值 |
is | 判断是否为某个值 |
get | 获取某个值 |
set | 设置某个值 |
推荐:
//是否可阅读
function canRead(){
return true;
}
//获取姓名
function getName{
return this.name
} 复制代码
每一个常量应该命名,否则看代码的人不知道这个常量表示什么意思。
推荐:
const COL_NUM = 10;
let row = Math.ceil(num/COL_NUM);复制代码
不推荐:
let row = Math.ceil(num/10);复制代码
建立对象和数组推荐使用字面量,由于这不只是性能最优也有助于节省代码量。
推荐:
let obj = {
name:'tom',
age:15,
sex:'男'
} 复制代码
不推荐:
let obj = {};
obj.name = 'tom';
obj.age = 15;
obj.sex = '男';复制代码
推荐:
const menuConfig = {
title: "Order",
// User did not include 'body' key
buttonText: "Send",
cancellable: true
};
function createMenu(config) {
config = Object.assign(
{
title: "Foo",
body: "Bar",
buttonText: "Baz",
cancellable: true
},
config
);
// config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true}
// ...
}
createMenu(menuConfig);
复制代码
不推荐:
const menuConfig = {
title: null,
body: "Bar",
buttonText: null,
cancellable: true
};
function createMenu(config) {
config.title = config.title || "Foo";
config.body = config.body || "Bar";
config.buttonText = config.buttonText || "Baz";
config.cancellable =
config.cancellable !== undefined ? config.cancellable : true;
}
createMenu(menuConfig);
复制代码
对象成员嵌套越深,读取速度也就越慢。因此好的经验法则是:若是在函数中须要屡次读取一个对象属性,最佳作法是将该属性值保存在局部变量中,避免屡次查找带来的性能开销。
推荐:
let person = {
info:{
sex:'男'
}
}
function getMaleSex(){
let sex = person.info.sex;
if(sex === '男'){
console.log(sex)
}
} 复制代码
不推荐:
let person = {
info:{
sex:'男'
}
}
function getMaleSex(){
if(person.info.sex === '男'){
console.log(person.info.sex)
}
}
复制代码
当须要将浮点数转换成整型时,应该使用Math.floor()
或者Math.round()
,而不是使用parseInt()
将字符串转换成数字。Math 是内部对象,因此
Math.floor()
其实并无多少查询方法和调用时间,速度是最快的。
推荐:
let num = Math.floor('1.6');复制代码
不推荐:
let num = parseInt('1.6');复制代码
函数参数越少越好,若是参数超过两个,要使用 ES6
的解构语法,不用考虑参数的顺序。
推荐:
function createMenu({ title, body, buttonText, cancellable }) {
// ...
}
createMenu({
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
});
复制代码
不推荐:
function createMenu(title, body, buttonText, cancellable) {
// ...
}
复制代码
使用参数默认值 替代 使用条件语句进行赋值。
推荐:
function createMicrobrewery(name = "Hipster Brew Co.") {
// ...
}
复制代码
不推荐:
function createMicrobrewery(name) {
const breweryName = name || "Hipster Brew Co.";
// ...
}复制代码
这是一条在软件工程领域流传久远的规则。严格遵照这条规则会让你的代码可读性更好,也更容易重构。若是违反这个规则,那么代码会很难被测试或者重用 。
在 JavaScript
中,永远不要污染全局,会在生产环境中产生难以预料的 bug
。举个例子,好比你在 Array.prototype
上新增一个 diff
方法来判断两个数组的不一样。而你同事也打算作相似的事情,不过他的 diff
方法是用来判断两个数组首位元素的不一样。很明显大家方法会产生冲突,遇到这类问题咱们能够用 ES2015/ES6
的语法来对 Array
进行扩展。
推荐:
class SuperArray extends Array {
diff(comparisonArray) {
const hash = new Set(comparisonArray);
return this.filter(elem => !hash.has(elem));
}
}复制代码
不推荐:
Array.prototype.diff = function diff(comparisonArray) {
const hash = new Set(comparisonArray);
return this.filter(elem => !hash.has(elem));
};
复制代码
函数式变编程可让代码的逻辑更清晰更优雅,方便测试。
推荐:
const programmerOutput = [
{
name: 'Uncle Bobby',
linesOfCode: 500
}, {
name: 'Suzie Q',
linesOfCode: 1500
}, {
name: 'Jimmy Gosling',
linesOfCode: 150
}, {
name: 'Gracie Hopper',
linesOfCode: 1000
}
];
let totalOutput = programmerOutput
.map(output => output.linesOfCode)
.reduce((totalLines, lines) => totalLines + lines, 0)
复制代码
不推荐:
const programmerOutput = [
{
name: 'Uncle Bobby',
linesOfCode: 500
}, {
name: 'Suzie Q',
linesOfCode: 1500
}, {
name: 'Jimmy Gosling',
linesOfCode: 150
}, {
name: 'Gracie Hopper',
linesOfCode: 1000
}
];
let totalOutput = 0;
for (let i = 0; i < programmerOutput.length; i++) {
totalOutput += programmerOutput[i].linesOfCode;
}复制代码
为了让代码更简洁易读,若是你的函数中出现了条件判断,那么说明你的函数不止干了一件事情,违反了函数单一原则 ;而且绝大数场景可使用多态替代
推荐:
class Airplane {
// ...
}
// 波音777
class Boeing777 extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude() - this.getPassengerCount();
}
}
// 空军一号
class AirForceOne extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude();
}
}
// 赛纳斯飞机
class Cessna extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}
复制代码
不推荐:
class Airplane {
// ...
// 获取巡航高度
getCruisingAltitude() {
switch (this.type) {
case '777':
return this.getMaxAltitude() - this.getPassengerCount();
case 'Air Force One':
return this.getMaxAltitude();
case 'Cessna':
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}
}复制代码
代码中使用了定时器 setTimeout
和 setInterval
,须要在不使用时进行清除。
利用scss
中的变量配置,能够进行项目的颜色、字体大小统一更改(换肤),有利于后期项目的维护。
推荐:
$--color-success: #67C23A;
$--color-warning: #E6A23C;
$--color-danger: #F56C6C;
$--color-info: #909399;
复制代码
scss
中的@import
规则在生成css
文件时就把相关文件导入进来。这意味着全部相关的样式被概括到了同一个css
文件中,而无需发起额外的下载请求,在构建咱们本身的组件库时推荐使用。
@import "./base.scss";
@import "./pagination.scss";
@import "./dialog.scss";
@import "./autocomplete.scss";
@import "./dropdown.scss";
@import "./dropdown-menu.scss";
复制代码
scss
局部文件的文件名如下划线开头。这样,scss
就不会在编译时单独编译这个文件输出css
,而只把这个文件用做导入。
推荐:
scss
的嵌套和父选择器标识符 & 能解决BEM
命名的冗长,且使样式可读性更高。
推荐:
.el-input {
display: block;
&__inner {
text-align: center;
}
}复制代码
mixin
混合器用来实现大段样式的重用,减小代码的冗余,且支持传参。
@mixin button-size($padding-vertical, $padding-horizontal, $font-size, $border-radius) {
padding: $padding-vertical $padding-horizontal;
font-size: $font-size;
border-radius: $border-radius;
&.is-round {
padding: $padding-vertical $padding-horizontal;
}
}
@include m(medium) {
@include button-size($--button-medium-padding-vertical, $--button-medium-padding-horizontal, $--button-medium-font-size, $--button-medium-border-radius);
}
@include m(small) {
@include button-size($--button-small-padding-vertical, $--button-small-padding-horizontal, $--button-small-font-size, $--button-small-border-radius);
}
复制代码
(1)使用@extend
产生 DRY CSS风格的代码(Don't repeat yourself)
(2)@mixin
主要的优点就是它可以接受参数。若是想传递参数,你会很天然地选择@mixin
而不是@extend
推荐:
.common-mod {
height: 250px;
width: 50%;
background-color: #fff;
text-align: center;
}
.show-mod--right {
@extend .common-mod;
float: right;
}
.show-mod--left {
@extend .common-mod;
}
复制代码
插值能动态定义类名的名称,当有两个页面的样式相似时,咱们会将相似的样式抽取成页面混合器,但两个不一样的页面样式的命名名称根据BEM
命名规范不能同样,这时咱们可以使用插值进行动态命名。
推荐:
@mixin home-content($class) {
.#{$class} {
position: relative;
background-color: #fff;
overflow-x: hidden;
overflow-y: hidden;
&--left {
margin-left: 160px;
}
&--noleft {
margin-left: 0;
}
}
}
复制代码
可经过each
遍历、map
数据类型、@mixin/@include
混合器、#{} 插值 结合使用,从而减小冗余代码,使代码更精简。
推荐:
$img-list: (
(xlsimg, $papers-excel),
(xlsximg, $papers-excel),
(gifimg, $papers-gif),
(jpgimg, $papers-jpg),
(mp3img, $papers-mp3),
(mp4img, $papers-mp3),
(docimg, $papers-word),
(docximg, $papers-word),
(rarimg, $papers-zip),
(zipimg, $papers-zip),
(unknownimg, $papers-unknown)
);
@each $label, $value in $img-list {
.com-hwicon__#{$label} {
@include commonImg($value);
}
}
复制代码
scss
自带函数的应用,从而进行相关的计算,例如 mix
函数的使用以下。
@include m(text) {
&:hover,
&:focus {
color: mix($--color-white, $--color-primary, $--button-hover-tint-percent);
border-color: transparent;
background-color: transparent;
}
&:active {
color: mix($--color-black, $--color-primary, $--button-active-shade-percent);
border-color: transparent;
background-color: transparent;
}
}
复制代码
gulp-sass
插件能实时监测scss
代码检查其语法错误并将其编译成css
代码,帮助开发人员检查scss
语法的准确性,且其是否符合咱们的预期,相关配置以下:
gulp.task('gulpsass', function() {
return gulp.src('src/style/components/hwIcon.scss')
.pipe(gulpsass().on('error', gulpsass.logError))
.pipe(gulp.dest('src/style/dest'));
});
gulp.task('watch', function() {
gulp.watch('src/style/components/hwIcon.scss', ['gulpsass']);
});
复制代码
咱们开发过程当中自定义的组件的名称须要为多个单词,这样作能够避免跟现有的以及将来的HTML
元素相冲突,由于全部的 HTML
元素名称都是单个单词的。
推荐:
Vue.component('todo-item', {
// ...
})
export default {
name: 'TodoItem',
// ...
}复制代码
不推荐:
Vue.component('todo', {
// ...
})
export default {
name: 'Todo',
// ...
}
复制代码
当在组件中使用 data
属性的时候 (除了 new Vue
外的任何地方),它的值必须是返回一个对象的函数。 由于若是直接是一个对象的话,子组件之间的属性值会互相影响。
推荐:
export default {
data () {
return {
foo: 'bar'
}
}
}复制代码
不推荐:
export default {
data: {
foo: 'bar'
}
}复制代码
prop
的定义应该尽可能详细,至少须要指定其类型。
推荐:
props: {
status: String
}
// 更好的作法!
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}复制代码
不推荐:
props: ['status'] 复制代码
v-for
中老是有设置 key
值。在组件上老是必须用 key
配合 v-for
,以便维护内部组件及其子树的状态。
推荐:
<ul>
<li
v-for="todo in todos"
:key="todo.id">
{{ todo.text }}
</li>
</ul>复制代码
不推荐:
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>复制代码
组件名应该倾向于完整单词而不是缩写,编辑器中的自动补全已经让书写长命名的代价很是之低了,而其带来的明确性倒是很是宝贵的。不经常使用的缩写尤为应该避免。
推荐:
components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue 复制代码
不推荐:
components/
|- SdSettings.vue
|- UProfOpts.vue 复制代码
在 JavaScript
中,用多行分隔对象的多个属性是很常见的最佳实践,由于这样更易读。
推荐:
<MyComponent
foo="a"
bar="b"
baz="c"
/>复制代码
不推荐:
<MyComponent foo="a" bar="b" baz="c"/> 复制代码
组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。复杂表达式会让你的模板变得不那么声明式。咱们应该尽可能描述应该出现的是什么,而非如何计算那个值。并且计算属性和方法使得代码能够重用。
推荐:
<!-- 在模板中 -->
{{ normalizedFullName }}
// 复杂表达式已经移入一个计算属性
computed: {
normalizedFullName: function () {
return this.fullName.split(' ').map(function (word) {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}
}复制代码
不推荐:
{{
fullName.split(' ').map(function (word) {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}}复制代码
应该把复杂计算属性分割为尽量多的更简单的属性。
推荐:
computed: {
basePrice: function () {
return this.manufactureCost / (1 - this.profitMargin)
},
discount: function () {
return this.basePrice * (this.discountPercent || 0)
},
finalPrice: function () {
return this.basePrice - this.discount
}
}复制代码
不推荐:
computed: {
price: function () {
var basePrice = this.manufactureCost / (1 - this.profitMargin)
return (
basePrice -
basePrice * (this.discountPercent || 0)
)
}
}复制代码
指令推荐都使用缩写形式,(用 : 表示 v-bind:
、用 @ 表示 v-on:
和用 # 表示 v-slot:
)。
推荐:
<input
@input="onInput"
@focus="onFocus"
>复制代码
不推荐:
<input
v-on:input="onInput"
@focus="onFocus"
>复制代码
单文件组件应该老是让标签顺序保持为 <template> 、<script>、 <style> 。
推荐:
<!-- ComponentA.vue -->
<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>复制代码
不推荐:
<!-- ComponentA.vue -->
<template>...</template>
<style>/* ... */</style>
<script>/* ... */</script>复制代码
父子组件的通讯推荐使用 prop
和 emit
,而不是this.$parent
或改变 prop
;
兄弟组件之间的通讯推荐使用 EventBus(on)
,而不是滥用 vuex
;
祖孙组件之间的通讯推荐使用listeners
或 provide / inject
(依赖注入) ,而不是滥用 vuex
;
页面跳转,例如 A 页面跳转到 B 页面,须要将 A 页面的数据传递到 B 页面,推荐使用 路由参数进行传参,而不是将须要传递的数据保存 vuex,而后在 B 页面取出 vuex的数据,由于若是在 B 页面刷新会致使 vuex 数据丢失,致使 B 页面没法正常显示数据。
推荐:
let id = ' 123';
this.$router.push({name: 'homeworkinfo', query: {id:id}}); 复制代码
script
标签内部的声明顺序以下:
data > prop > components > filter > computed > watch >
钩子函数(钩子函数按其执行顺序)> methods复制代码
(1)推荐使用计算属性:计算属性基于响应式依赖进行缓存,只在相关响应式依赖发生改变时它们才会从新求值;相比之下,每次调用方法都会再次执行方法;
(2)推荐使用计算属性:而不是根据 Watch
侦听属性,进行回调; 可是有计算属性作不到的:当须要在数据变化时执行异步或开销较大的操做时,侦听器是最有用的。
v-if
是“真正”的条件渲染,由于它会确保在切换过程当中条件块内的事件监听器和子组件适当地被销毁和重建。 v-if
也是惰性的:若是在初始渲染时条件为假,则什么也不作——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——无论初始条件是什么,元素老是会被渲染,而且只是简单地基于 CSS
的属性 display
进行切换。
推荐:
若是运行时,须要很是频繁地切换,推荐使用 v-show
比较好;若是在运行时,条件不多改变,则推荐使用 v-if
比较好。
由于团队如今使用 vue
框架,因此在项目开发中尽可能使用 vue
的特性去知足咱们的需求,尽可能(不到万不得已)不要手动操做DOM
,包括:增删改dom
元素、以及更改样式、添加事件等。
不少时候有些代码已经没有用了,可是没有及时去删除,这样致使代码里面包括不少注释的代码块,好的习惯是提交代码前记得删除已经确认弃用的代码,例如:一些调试的console
语句、无用的弃用代码。
代码注释不是越多越好,保持必要的业务逻辑注释,至于函数的用途、代码逻辑等,要经过语义化的命令、简单明了的代码逻辑,来让阅读代码的人快速看懂。
辛苦整理良久,若是对你有帮助,还望手动点赞鼓励~~~~~~
github地址为:github.com/fengshi123/…,若是喜欢或者有所启发,请帮忙给个 star ~,对做者也是一种鼓励。
一、clean-code-javascript
:github.com/ryanmcdermo…
二、SCSS
— 缩减50%的样式代码 : juejin.im/post/5c4888…
三、vue cookbook
:cn.vuejs.org/v2/cookbook…