转自微信公众号:小生方勤
原文链接:https://mp.weixin.qq.com/s/gMCngLbxBOuTz5yevvWtpQ
标准与每个团队和集体都是非亲非故的,因为其影响的不只是代码的保护和了解老本,重大的时候是会影响成员开发的情绪
一个团队的编码标准、git 标准等,并没有相对的最优解,心里要分明明确 没有银弹
,标准是为了让团队对立,进步代码浏览性、升高代码保护老本等,本文是记录一些在我的项目 code review
中常见的标准,仅供参考
JS 局部
vue
中 data
的数据默认便会进行双向数据绑定,若是将大量的和渲染无关的数据间接搁置在 data
中,将会节约双向数据绑定时所耗费的性能,将这些和渲染无关的数据进行抽离并配合 Object.freeze
进行解决
table
中 columns
数据能够独自提取一个内部 js
文件作为配置文件,也能够在以后 .vue
文件中定义一个常量定义 columns
数据,因为无论如何都是固定且不会批改的数据,应该应用 Object.freeze
进行包裹,既能够进步性能还能够将固定的数据抽离,一些下拉框前端固定的数据也倡议此操作
const columnList = Object.freeze([{ title: '姓名', key: 'name', align: 'center'},
{title: '性别', key: 'gender', align: 'center'},
])
须要留神的是 Object.freeze() 解冻的是值,这时依然能够将变量的援用替换掉,还有确保数据不会变才能够应用这个语法,如果要对数据进行批改和交互,就不适宜应用解冻了。
Modal 框的管制
一个页面种通常会存在很多个不同性能的弹框,若是每一个弹框都设置一个对应的变量来管制其显示,则会导致变量数量比拟冗余和命名艰难,能够应用一个变量来管制同一页面中的所有 Modal
弹框的展现
比方某个页面中存在三个 Modal
弹框
// bad
// 每一个数据管制对应的 Modal 展现与暗藏
new Vue({data() {
return {
modal1: false,
modal2: false,
modal3: false,
}
}
})
// good
// 当 modalType 为对应的值时 展现其对应的弹框
new Vue({data() {
return {modalType: // modalType 值为 modal1,modal2,modal3}
}
})
debounce 应用
例如近程搜寻时须要通过接口动静的获取数据,若是每次用户输出都接口申请,是节约带宽和性能的
当一个按钮屡次点击时会导致屡次触发事件,能够联合场景是否立刻执行 immediate
<Select :remote-method="remoteMethod">
<Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
import {debounce} from lodash
methods:{remoteMethod:debounce(function (query) {
// to do ...
// this 的指向没有问题
}, 200),
}
图片
性能的开发过程中,图片的解决往往是比拟容易被疏忽的环节,也会在肯定水平影响开发的效率和页面的性能
- 图片压缩问题,除非特地要求图片必须高质量的显示,否则都应该进行对应的压缩解决
-
不同业务场景进行图片格式的选型
- JPG 实用于出现色调丰盛的图片,JPG 图片常常作为大的背景图、轮播图或 Banner 图呈现等
- Logo、色彩简略且比照强烈的图片或背景、须要透明度等
- 将罕用且变动频率很低的小图片进行合并成雪碧图,对于变动比拟频繁和小于
6KB
的图片进行base64
解决 - 依据我的项目图片数量和我的项目的用户机型散布等,思考采取
webp
进行图片的解决
路由组件传参
在组件中应用
$route
会使之与其对应路由造成高度耦合,从而使组件只能在某些特定的 URL 上应用,限度了其灵活性。
应用 props
将组件和路由解耦:
取代与 $route
的耦合
const User = {template: <div>User {{ $route.params.id}}</div>
}
const router = new VueRouter({
routes: [{ path: /user/:id , component: User}
]
})
通过 props
解耦
这样你便能够在任何中央应用该组件,使得该组件更易于重用和测试。
const User = {props: [ id],
template: <div>User {{id}}</div>
}
const router = new VueRouter({
routes: [{ path: /user/:id , component: User, props: true},
// 对于蕴含命名视图的路由,你必须别离为每个命名视图增加 `props` 选项:{
path: /user/:id ,
components: {default: User, sidebar: Sidebar},
props: {default: true, sidebar: false}
}
]
})
参考:路由组件传参
Vue 生命周期
在父子组件中,把握父子组件对应的生命周期钩子加载程序能够让开发者在更适合的时候做适宜的事件
1. 父组件
<template>
<div>
<h3>home</h3>
<list @hook:mounted="listMounted" />
</div>
</template>
<script>
import List from ./list
export default {
name: "home",
components: {List},
methods: {listMounted(){console.log( ------------ listMounted);
}
},
beforeCreate() {console.log("home beforeCreate");
},
created() {console.log("home created");
},
beforeMount() {console.log("home beforeMount");
},
mounted() {console.log("home mounted");
},
beforeDestroy() {console.log("home beforeDestroy");
},
destroyed() {console.log("home destroyed");
}
}
</script>
2. 子组件
<template>
<div>
list
</div>
</template>
<script>
export default {
naem: "list",
beforeCreate() {console.log("list beforeCreate");
},
created() {console.log("list created");
},
beforeMount() {console.log("list beforeMount");
},
mounted() {console.log("list mounted");
},
beforeDestroy() {console.log("list beforeDestroy");
},
destroyed() {console.log("list destroyed");
}
}
</script>
3. 加载时父子组件的加载程序
home beforeCreate --> home created --> home beforeMount --> list created --> list beforeMount --> list mounted
4. 销毁时父子组件的销毁程序
home beforeDestroy --> list beforeDestroy --> list destroyed --> home destroyed
理论开发过程中会遇到当子组件某个生命周期实现之后告诉父组件,而后在父组件做对应的解决
5. emit up
// 子组件在对应的钩子中公布事件
created(){this.$emit( done)
}
// 父组件订阅其方发
<list @done="childDone">
6. hook
通过 @hook
监听子组件的生命周期
<list @hook:mounted="listMounted"><br></list>
Select 优化
下拉框遍历时,须要留神 options
标签放弃同一行,若是存在换行,会导致选中时的值存在多余的空白
// bad
<Select :remote-method="remoteMethod">
<Option v-for="item in temoteList" :value="item.value" :key="item.id">
{{item.label}}
</Option>
</Select>
须要将 Options
和下拉框的值放弃在同一行
// good
<Select :remote-method="remoteMethod">
<Option v-for="item in temoteList" :value="item.value" :key="item.id">{{item.label}}</Option>
</Select>
data 数据层级
data
数据具备数据层级构造,切勿适度扁平化或者嵌套层级过深,若是适度扁平化会导致数据命名空间抵触,参数传递和解决,若是层级嵌套过深也会导致 vue
数据劫持的时候递归层级过深,若是嵌套层级丧心病狂那种的,小心递归爆栈的问题。而且层级过深会导致数据操作和解决不便,获取数据做容错解决也比拟繁琐。个别层级放弃 2-3 层最好。
若是只有一层数据,过于扁平
{
name:'',
age:'',
gender:''
}
导致解决不不便
// 作为接口参数传递
ajax({this.name, this.age, this.gender})
// 接口获取数据,批量解决
ajax().then(res => {const {name, age, gender} = res.data
this.name = name
this.age = age
this.gender = gender
})
适当的层级构造不仅减少代码的保护和浏览性,还能够减少操作和解决的便捷性
{
person: { // 个人信息
name:'',
age:'',
gender:''
}
}
能够针对 person
进行操作
// 作为接口参数传递
ajax(this.person)
// 接口获取数据,批量解决
ajax().then((res) => {const { name, age, gender} = res.data
this.$set(this, person, { name, age, gender})
})
策略模式
策略模式的应用,防止过多的 if else
判断,也能够代替简略逻辑的 switch
const formatDemandItemType = (value) => {switch (value) {
case 1:
return '根底'
case 2:
return '高级'
case 3:
return 'VIP'
}
}
// 策略模式
const formatDemandItemType2 = (value) => {
const obj = {
1: '根底',
2: '高级',
3: 'VIP',
}
return obj[value]
}
解构
解构赋值以及默认值,当解构的数量小于多少时适宜间接解构并赋值默认值,数据是否进行相干的聚合解决
const {name = '', age = 10, gender ='man'} = res.data
// bad
this.name = name
this.age = age
this.gender = gender
// good
this.person = {
name,
age,
gender,
}
职责繁多
任何时候尽量是的一个函数就做一件事件,而不是将各种逻辑全副耦合在一起,进步单个函数的复用性和可读性
每个页面都会在加载实现时进行数据的申请并展现到页面
created() {this.init();
},
methods: {
// 将全副的申请行为聚合在 init 函数中
// 将每个申请独自拆分
init() {this.getList1()
this.getList2()},
getList1() {// to do ...},
getList2() {// to do ...}
}
HTML 局部
html 书写
编写 template
模板时,属性过多时,是否换行
<template>
<!-- 不换行 -->
<VueButton class="icon-button go-up" icon-left="keyboard_arrow_up" v-tooltip="$t(org.vue.components.folder-explorer.toolbar.tooltips.parent-folder)" @click="openParentFolder" />
<!-- 换行 -->
<VueButton
class="icon-button go-up"
icon-left="keyboard_arrow_up"
v-tooltip="$t(org.vue.components.folder-explorer.toolbar.tooltips.parent-folder)"
@click="openParentFolder"
/>
</template>
CSS 局部
款式穿透
在开发中批改第三方组件款式是很常见,但因为 scoped
属性的款式隔离,可能须要去除 scoped
或是另起一个 style
。这些做法都会带来副作用(组件款式净化、不够优雅),款式穿透在 css 预处理器中应用才失效。
- less 应用 /deep/
<style scoped lang="less">
.content /deep/ .el-button {height: 60px;}
</style>
- scss 应用 ::v-deep
<style scoped lang="scss">
.content ::v-deep .el-button {height: 60px;}
</style>
- stylus 应用 >>>
<style scoped ang="stylus">
.content >>> .custon-components {height: 60px;}
</style>
空格
适当的空格能够晋升代码的浏览体验,显得更为优雅和好看
选择器后、属性值
.custom-style {
/* 选择器和{ 之间空格 */
margin: 0; /* 属性值前 */
transform: scale(1.5, 2.2); /* 逗号之后减少空格 */
}
换行
和 html
类型,当某行的属性很多,适当的换行能够进步浏览和好看
.custom-style {
/* 能够在一次申明中定义一个或多个属性 */
background: background-clip background-color background-image
background-origin background-position background-repeat background-size;
}
当一个规定蕴含多个选择器时,每个选择器申明必须独占一行,过长导致须要横向滚动浏览残余的内容,应该尽量使得浏览程序纵向化
.custom .header .title,
.other .header .title {color: #f0f;}
嵌套层级
浏览器在解析 css
时,是依照从右到左递归匹配的,过深的层级嵌套不仅影响性能,而且还会导致款式浏览性和代码维护性升高,个别层架管制在 5层之内
属性程序
同一 规定下的属性在书写时,应按性能进行分组。并以 Formatting Model(布局形式、地位)> Box Model(尺寸)> Typographic(文本相干)> Visual(视觉效果)的程序书写,以进步代码的可读性。
解释:
- Formatting Model 相干属性包含:position / top / right / bottom / left / float / display / overflow 等
- Box Model 相干属性包含:border / margin / padding / width / height 等
- Typographic 相干属性包含:font / line-height / text-align / word-wrap 等
- Visual 相干属性包含:background / color / transition / list-style 等
另外,为减少可读性,如果蕴含 content 属性,应放在属性的最后面。
原文链接