开发者(KaiFaX)

我们都是开发者
专注于前端、后端、大数据、区块链、人工智能的知识社区

来源:

https://www.javascriptcn.com/read-5ecef0f64d553e7cc39e1aba.html

规范与每个团队和个人都是息息相关的,因为其影响的不只是只是代码的维护和理解成本,严重的时候是会影响成员开发的心情

一个团队的编码规范、git规范等,并没有绝对的最优解,心里要清楚明白没有银弹,规范是为了让团队统一,提高代码阅读性、降低代码维护成本等,本文是记录一些在项目code review中常见的规范,仅供参考

JS部分

和渲染无关的数据

vuedata的数据默认便会进行双向数据绑定,若是将大量的和渲染无关的数据直接放置在data中,将会浪费双向数据绑定时所消耗的性能,将这些和渲染无关的数据进行抽离并配合Object.freeze进行处理

tablecolumns数据可以单独提取一个外部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生命周期

在父子组件中,掌握父子组件对应的生命周期钩子加载顺序可以让开发者在更合适的时候做适合的事情父组件

<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>

子组件

<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>

加载时父子组件的加载顺序

home beforeCreate --> home created --> home beforeMount --> list created --> list beforeMount --> list mounted

销毁时父子组件的销毁顺序

home beforeDestroy --> list beforeDestroy --> list destroyed --> home destroyed

实际开发过程中会遇到当子组件某个生命周期完成之后通知父组件,然后在父组件做对应的处理

emit up

// 子组件在对应的钩子中发布事件
created(){this.$emit('done')
}// 父组件订阅其方发
<list @done="childDone">

hook

通过@hook监听子组件的生命周期

<list @hook:mounted="listMounted" />

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.datathis.name = namethis.age = agethis.gender = gender
})

适当的层级结构不仅增加代码的维护和阅读性,还可以增加操作和处理的便捷性

{person: { // 个人信息name: '',age: '',gender: ''}
}

可以针对person进行操作

// 作为接口参数传递
ajax(this.person)// 接口获取数据,批量处理
ajax().then(res => {const {name, age, gender} = res.datathis.$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 {naem = '',age = 10,gender = 'man'
} = res.data// bad
this.name = name
this.age = age
this.gender = gender// good
this.person = {naem,age,gender
}

职责单一

任何时候尽量是的一个函数就做一件事情,而不是将各种逻辑全部耦合在一起,提高单个函数的复用性和可读性

每个页面都会在加载完成时进行数据的请求并展示到页面

created() {this.init();
},
methods: {// 将全部的请求行为聚合在init函数中// 将每个请求单独拆分init() {this.getList1()this.getList2()},getList1() {// to do ...},getList2() {// to do ...}
}

v-bind

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" /><!-- 换行 --><VueButtonclass="icon-button go-up"icon-left="keyboard_arrow_up"v-tooltip="$t('org.vue.components.folder-explorer.toolbar.tooltips.parent-folder')"@click="openParentFolder"/>
</template>

实体使用

html中展示一些如<>,&等字符时,使用字符实体代替

<!-- bad -->
<div>> 1 & < 12
</div><!-- bad -->
<div>&gt; 1 &amp; &lt; 12
</div>

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">
外层 >>> .custon-components{height: 60px;
}
</style>

空格

适当的空格可以提升代码的阅读体验,显得更为优雅和美观

选择器后、属性值

.custom-style { // 选择器和{ 之间空格margin: 0; // 属性值前transform: scale(1.5, 2.2); // 逗号之后增加空格
}

换行

html类型,当某行的属性很多,适当的换行可以提高阅读和美观

.custom-style{// 可以在一次声明中定义一个或多个属性background: background-clipbackground-colorbackground-imagebackground-originbackground-positionbackground-repeatbackground-size;
}

当一个规则包含多个选择器时,每个选择器声明必须独占一行,过长导致需要横向滚动阅读剩余的内容,应该尽量使得阅读顺序纵向化

.custom .header .title,
.other .header .title {color: #f0f;
}

嵌套层级

浏览器在解析css时,是按照从右到左递归匹配的,过深的层级嵌套不仅影响性能,而且还会导致样式阅读性和代码维护性降低,一般层架控制在5层之内

双引号

属性选择器中的值必须用双引号包围,不允许使用单引号,也不允许不使用引号,html的属性值也是推荐使用双引号,js中使用单引号

.custom-style{
font-family: "PingFang SC", "STHeitiSC-Light";
}

属性顺序

同一 规则下的属性在书写时,应按功能进行分组。并以 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 属性,应放在属性的最前面。

参考

  • 三年 Vue 前端开发的血与泪总结

  • 编码规范作用


1. 回复“m”可以查看历史记录;

2. 回复“h”或者“帮助”,查看帮助;

开发者已开通多个技术群交流学习,请加若飞微信:1321113940 进开发群学习交流

说明:我们都是开发者。视频或文章来源于网络,如涉及版权或有误,请您与若飞(1321113940)联系,将在第一时间删除或者修改,谢谢!

开 发 者 : KaiFaX

我们都是开发者

专注于前后端、大数据、区块链、人工智能的知识社区

在看支持一下❤️

Vue编程的团队代码规范相关推荐

  1. vue获取当前选中行的数据_Vue编程的团队代码规范

    来源:https://www.javascriptcn.com/read-5ecef0f64d553e7cc39e1aba.html 规范与每个团队和个人都是息息相关的,因为其影响的不只是只是代码的维 ...

  2. Vue eslint 团队代码规范

    原文:nice.lovejade.cn/zh/article/- Prettier 是一个有见识的代码格式化工具.它通过解析代码并使用自己的规则重新打印它,并考虑最大行长来强制执行一致的样式,并在必要 ...

  3. python编程基础(四):编程习惯、代码规范、易混淆之处

    目录 编程习惯 代码规范 python中self的作用 易混淆之处 编程习惯 1. 添加主函数if __name__ == 'main': 2. 使用project_path = os.getcwd( ...

  4. 【总结】1165- 前端团队代码规范最佳实践,个人成长必备!

    作者:杨成功 原文:https://segmentfault.com/a/1190000040948561 本文从代码规范,代码检查,代码格式化,以及编辑器自动化实现的方向,介绍代码规范统一在我们团队 ...

  5. 前端团队代码规范最佳实践,个人成长必备!

    大厂技术  高级前端  Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 作者:杨成功 原文:https://segmentfault.com/a/119000004 ...

  6. 前端团队代码规范最佳实践!

    点击上方关注 前端技术江湖,一起学习,天天进步 作者:杨成功 原文:https://segmentfault.com/a/1190000040948561 本文从代码规范,代码检查,代码格式化,以及编 ...

  7. 团队代码规范java,java 开发,适用于团队的代码规范及某些约定

    包含 api 开发原则.代码风格.mapper 扩展等. api 开发总则遵循单一职责原则,一个类只做一件(类)事. 数据库表与业务类是 1:N 的关系. 简单业务表建议只有一个业务类,复杂业务表,建 ...

  8. C/C++编程:Google代码规范

    头文件 除了单元测试只有.cc外,其他每一个.cc都应该有一个对应的.h Self-contained 头文件 就是说要保证你的头文件是自给自足的,一个自足的头文件是一个不依赖于它包含在那里的上下文来 ...

  9. 一套流程教你完成基于vue脚手架的vscode代码规范(vetur+eslint+prettier)配置

    在写代码的过程当中一般都会要求生产统一风格的代码.规范,简洁的代码好处就不用我多说了吧.接下来就按我的方法来初始化代码生产环境吧. 配置步骤 1.在vscode中下载三个插件 vetur,Pretti ...

最新文章

  1. python3 列表转字节_Python 3.9!10大新特性值得关注
  2. java的断点条件,java – Eclipse Debugger不会在条件断点处停止
  3. pythonseleniumAPI
  4. CAS无锁(乐观锁、自旋锁)优化
  5. php mysql foreach_php foreach输出两次
  6. [MFC]关于Visual studio 2012的AfxGetMainWnd
  7. MySQL数据类型及后面小括号的意义
  8. 防止刷新重复post提交
  9. python中关于深嵌元组转列表的小问题
  10. 计算机丢失w95scm.dll,修复w95scm.dll
  11. 信息论与编码之信源编码详解
  12. 【一年总结】记我的大二生活
  13. 降水数据下载地址汇总
  14. 去广告神器(Adblock Plus离线安装)
  15. 工作流:企业OA办公系统的核心
  16. 2012年9月世界编程语言排行榜!
  17. MPI以太网通讯处理器在铝型材时效炉中的实际应用案例
  18. windows7资源管理器中增加XP下的摄像头图标
  19. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting
  20. 2019奥迪创新实验室大赛招募第一弹|趁现在,定一份未来出行计划

热门文章

  1. 开源资料:firework 脚本方面的资料
  2. pytorch Con2d详解
  3. 人工智能技术会代替人类的工作吗
  4. 计算机硬件系统(一)
  5. ③⭐全网首发☀️数据有道之数据库技术❤️干货大全【持续更新】❗❗❗
  6. Hibernate QBC与QBE
  7. 显著性物体检测与分割
  8. CheckBox的使用
  9. s:checkbox
  10. 医学图像处理(一)——分割中常用的度量指标