文章目录
前言
前端开发是一个涉及多种技术和语言的领域,如 HTML、CSS、JavaScript、Vue 等。为了让前端代码更优雅和易读,我们需要遵循一些编码规范和最佳实践,让我们的代码更清晰、更有意义、更易于理解和沟通。本文将介绍一些常见的前端编码规范和建议,希望对你有所帮助。
提示:以下是本篇文章正文内容,下面案例可供参考,如有不同意见可以提出一起探讨
一、如何优化代码?
1.if 和 return 的结合使用及if嵌套
原理:return语句将终止当前函数并返回当前函数的值,使用if+return可以大大提高代码阅读性,避免使用else和elseif嵌套if,如果else或者else-if写多了,代码缩进会很难看,让人望而却步
优化前
navurl7() {
if (this.hasLogin) {
this.rolesData().then((res) => {
if (res.data == 3) {
uni.navigateTo({
url: '/pages/franchisee/index',
})
}else {
uni.navigateTo({
url: '/pages/attractInvestment/index',
})
}
})
} else {
uni.navigateTo({
url: '/pages/login/index',
})
}
},
优化后
navurl7() {
if (!this.hasLogin) return uni.navigateTo({
url: "/pages/login/index" });
//符合上述条件,此处代码不会执行
this.rolesData().then((res) => {
if (res.data !== 3) return uni.navigateTo({
url: "/pages/attractInvestment/index" });
uni.navigateTo({
url: "/pages/franchisee/index",
});
});
},
2.ES6之async与await
原理:promise是异步的,使用async和await可以让代码看起来像同步的,省去了.then的步骤,有效解决回调地狱的问题,什么?你问我什么是回调地狱?就是
this.xxxxx1().then((res1) => {
// do something
this.xxxxx2().then((res2) => {
// do something
this.xxxxx3().then((res3) => {
// do something
this.xxxxx4().then((res4) => {
// do something
this.xxxxx5().then((res5) => {
// do something
});
});
});
});
});
优化前
navurl7() {
if (!this.hasLogin) return uni.navigateTo({
url: "/pages/login/index" });
this.rolesData().then((res) => {
if (res.data !== 3) return uni.navigateTo({
url: "/pages/attractInvestment/index" });
uni.navigateTo({
url: "/pages/franchisee/index",
});
});
},
优化后
async navurl7() {
if (!this.hasLogin) return uni.navigateTo({
url: "/pages/login/index" });
let result = await this.rolesData();
if (result.data !== 3) return uni.navigateTo({
url: "/pages/attractInvestment/index" });
uni.navigateTo({
url: "/pages/franchisee/index" });
},
这时候再看看第一步,从18行代码优化到6行,代码更容易读懂,更简洁
3.ES6之lastIndexOf函数
原理:Array中的lastIndexOf方法返回符合条件的子项目下标,用此函数可简化下述功能代码
优化前
hotliveClick(id, pic) {
plus.share.getServices(function(res){
console.log(res)
var sweixin = null;
for(var i = 0; i < res.length; i++){
var t = res[i];
if(t.id == 'weixin'){
sweixin = t;
}
}
if(sweixin){
sweixin.launchMiniProgram({
id: 'gh_7b33e2a22ed9', //这里写你的小程序原始id(以gh开头)
type: 0, //这里是不同的环境(默认0)
path:'/page/me/live/live_find/find?id=' + id + '&pic=' + pic //这里是指定页的路径,如需传参直接字符串拼接(首页可以省略)
});
}
},function(err){
console.log(err);
})
}
优化后
hotliveClick(id, pic) {
plus.share.getServices((res) => {
const lastIndex=res.lastIndexOf((v) => v.id === "weixin")
if (lastIndex===-1) return;
res[lastIndex].launchMiniProgram({
id: "gh_7b33e2a22ed9",
type: 0,
path: "/page/me/live/live_find/find?id=" + id + "&pic=" + pic,
});
});
},
4.避免嵌套循环
原理:估计写代码最怕遇到这种头疼的循环了,善用es6,避免嵌套循环~~
优化前
getFlagArrs(m, n) {
var flagArrs = [],
flagArr = [],
isEnd = false
for (var i = 0; i < m; i++) {
flagArr[i] = i < n ? 1 : 0
}
flagArrs.push(flagArr.concat())
// 当n不等于0并且m大于n的时候进入
if (n && m > n) {
while (!isEnd) {
var leftCnt = 0
for (var i = 0; i < m - 1; i++) {
if (flagArr[i] == 1 && flagArr[i + 1] == 0) {
for (var j = 0; j < i; j++) {
flagArr[j] = j < leftCnt ? 1 : 0
}
flagArr[i] = 0
flagArr[i + 1] = 1
var aTmp = flagArr.concat()
flagArrs.push(aTmp)
if (aTmp.slice(-n).join('').indexOf('0') == -1) {
isEnd = true
}
break
}
flagArr[i] == 1 && leftCnt++
}
}
}
return flagArrs
},
优化后
鄙人不才,光看代码没看出想表达什么,只要不出问题,这个代码我是不会动的,如果要动,大概率重构
5.uniapp路由封装
优化前
uni.navigateTo({
url: '/pages/order/placeOrderPt?grouponGoodsId=' + that.grouponGoodsId + '&number=' + that.berbox + '&productId='+ that.sku
})
优化后
/**
* 封装uniapp路由hook
* @returns 路由跳转方法
*/
export const useRouter = () => {
/**
* 把对象转成query格式:aaa=bbb&ccc=ddd
* @param obj
* @returns
*/
function mapObjectToQueryString(obj: Object) {
if (!obj) return ""
var str = [];
for (let p in obj) {
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
}
return "&" + str.join("&");
}
/**
*
* @param url 跳转地址
* @param params 跳转参数
*/
const push = <T>(url: string, params?: T) => {
let completeUrl = params ? `${
url}?${
mapObjectToQueryString(params ?? {
})}` : url
uni.navigateTo({
url: completeUrl,
})
}
/**
*
* @param params 跳转参数
*/
const back = () => {
uni.navigateBack({
delta: 1
})
}
/**
* 跳转至某页面,关闭其他所有页面并不能返回
* @param url 跳转地址
* @param params 跳转参数
*/
const replace = <T>(url: string, params?: T) => {
let completeUrl = params ? `${
url}?${
mapObjectToQueryString(params ?? {
})}` : url
uni.redirectTo({
url: completeUrl,
})
}
/**
* 跳转至某页面,关闭其他所有页面并不能返回
* @param url 跳转地址
* @param params 跳转参数
*/
const switchTab = <T>(url: string, params?: T) => {
let completeUrl = params ? `${
url}?${
mapObjectToQueryString(params ?? {
})}` : url
uni.switchTab({
url: completeUrl,
})
}
return {
push, replace, switchTab, back }
}
const router=useRouter()
router.push("xxxx/xxxx/xxxx",{
id:xxx,name:xxxx,age:xxx,others:xxx})
6.includes解决多条件判断
原理:Array.includes()接收一个值,如果数组中任何一个值与传入值一样,返回true,否则返回false
优化前
if (props.orginItem.historyType === 2 || props.orginItem.historyType === 3 || props.orginItem.historyType === 5) {
// do something
}
优化后
if ([2,3,5].includes(props.orginItem.historyType)) {
// do something
}
7.简单的代码能写一行写一行
优化前
const testArr = someArr.map(item => {
return {
...item,
someKey: item.someKey1 + item.someKey2
}
})
优化后
const testArr = someArr.map(item => ({
...item, someKey: item.someKey1 + item.someKey2 }))
9.链式调用
例:
const arr = state.totalFlatTree
.map(v => ({
...v, checked: !!props.modelValue.includes(v.nodeId) }))
.filter(v => v.nodeType === 1)
.sort((a, b) => a.nodeId - b.nodeId)
.reduce((pre, cur) => `${
pre}${
cur.nodeName}`, "")
10.合理利用Boolean转换规则做if判断
原理:在js中,undefined、null、 +0、-0、‘’(空字符串)、NaN转为布尔值全都为false
假设后端给一个条件,返回值是0或者1但不排除为null
优化前
if(xxx===0){
// do something
// xxx=null时不执行
}
if(xxx===1){
// do something
// xxx=null时不执行
}
优化后
if(!xxx){
// do something
// xxx=null或者xxx=0时执行
}
if(xxx){
// do something
// xxx=null时不执行
}
11.对select选择器的选项做统一封装并且写json注释
日常写代码接触到表单或者是筛选的时候,基本都会用到选择器,可能其他模块也会用到这些选项,如果不做封装就会疯狂ctrl+c,ctrl+v,,写的时候可能觉得方便,但如果后面需要加某些选项,稍有不慎就会出现遗漏
大多数人写注释可能习惯//的方式这种在代码中是没有智能提示的,但如果使用json注释 /** */是会有提示的
例子
// xxxx.ts
/**
* 事件等级
*/
export const eventLevelOptions = [
{
label: "全部", value: -1 },
{
label: "一级事件", value: 1 },
{
label: "二级事件", value: 2 },
{
label: "三级事件", value: 3 },
{
label: "四级事件", value: 4 },
];
/**
* 初信初访
*/
export const eventFirstTypeOptions = [
{
label: "初信初访", value: 1 },
{
label: "重复访", value: 2 },
]
12.合理利用hooks节省代码量
这里看我之前写的一篇文章
https://blog.csdn.net/wz9608/article/details/128189567?spm=1001.2014.3001.5502
13.跳转页面,把跳转参数做封装
日常我们可能会用到几个不同的功能,很类似,选择使用同一个页面,例如:表单新增,表单修改,
有些人可能喜欢多复制几个页面,但是当功能复杂后,修改需要改多个页面,非常的不友好,但写在同一个页面的时候,参数怕搞混,这时候我们把跳转的参数做一层封装,让它更语义化,并写上注释
优化前
// 跳转之前一个页面
router.push({
path:"xxxx",query:{
type:1}})
// 页面中
if(route.query.type==="1"){
//do something
}
if(route.query.type==="2"){
//do something
}
优化后
// xxx.ts
// 这里用的ts枚举类型,js用对象代替即可
/**
* 事件选择页面模式
*/
export enum TEventSelectMode {
/** 重复访 */
CREATE_AGAIN = "crate_again",
/** 返回表单 */
BACK_FORM = "back_form",
/** 直接关联事件 */
ABOUT_EVENT = "about_event",
/** 四级创建 */
FOUR_CREATE = "four_create"
}
// 跳转之前一个页面
router.push({
path:"xxxx",query:{
mode:TEventSelectMode.CREATE_AGAIN}})
// 页面中
if(route.query.mode===TEventSelectMode.CREATE_AGAIN){
//do something
}
if(route.query.mode===TEventSelectMode.BACK_FORM){
//do something
}
14.1000个if怎么写?用分支优化
优化前
function dosomethingByName(name: string) {
if (name === "xxx") {
this.xxx()
} else if (name === "xxx1") {
this.xxx1()
} else if (name === "xxx2") {
this.xxx2()
} else if (name === "xxx3") {
this.xxx3()
} else if (name === "xxx4") {
this.xxx4()
} else if (name === "xxx5") {
this.xxx5()
} else {
this.xxx6()
}
}
优化后
function dosomethingByName(name: string) {
const objcet = {
"xxx": () => this.xxx(),
"xxx1": () => this.xxx1(),
"xxx2": () => this.xxx2(),
"xxx3": () => this.xxx3(),
"xxx4": () => this.xxx4(),
"xxx5": () => this.xxx5(),
}
// || this.xxx6() 相当于else
objcet[name]() || this.xxx6()
}
15.杜绝自增命名
优化前
// 某同事在data中定义了这么一串东西
detailVisible1: false,
detailVisible2: false,
detailVisible3: false,
detailVisible4: false,
detailVisible5: false,
detailVisible6: false,
detailVisible7: false,
detailVisible8: false,
优化后
// 建议打上json注解
/** 预警详情 */
wraningVisibel: boolean;
/** 调处详情 */
mediationDetailVisibel: boolean;
/** 上报详情 */
escalationDetailVisibel: boolean;
/** 研判驳回 */
judgmentRejectVisibel: boolean
二、命名规范
命名是个让人很头疼的问题,很多人取出来的名字千奇百怪,命名是编程中最基本也最重要的一项工作,一个好的命名可以让代码更清晰、更有意义、更易于理解和沟通。以下是一些命名规范的要点:
- 项目命名:全部采用小写方式,以中划线分隔,如
my-project
。 - 目录命名:全部采用小写方式,以中划线分隔,有复数结构时,要采用复数命名法,缩写不用复数,如
components
、assets
。 - 文件命名:全部采用小写方式,以中划线分隔,如
index.html
、main.js
、style.css
。 - 变量命名:采用小写驼峰命名法(lowerCamelCase),即第一个单词首字母小写,后面单词首字母大写,如
userName
、isLogin
。 - 常量命名:全部大写,单词间用下划线隔开,如
MAX_LENGTH
、API_URL
。 - 函数命名:采用小写驼峰命名法(lowerCamelCase),并且要能体现函数的功能或作用,如
getData
、handleClick
。 - 类命名:采用大写驼峰命名法(UpperCamelCase),即每个单词首字母都大写,如
User
、Product
。 - 组件命名:采用大写驼峰命名法(UpperCamelCase),并且使用完整单词而不是缩写,如
Header
、Footer
。 - ts类型命名:采用大写驼峰命名(UpperCamelCase),并且加上类型前缀,如接口(interface)命名
IState
、IUserInfo
- 请求接口命名:采用req前缀+大写驼峰命名(UpperCamelCase),如
reqGetUserInfo
、reqGetUserList
。
总结
以上就是我对前端开发过程中,让代码更优雅、更容易读的方法的一些总结和建议。当然,这些方法并不是一成不变的,也不是唯一正确的。不同的项目和团队可能有不同的需求和风格。但是我认为,无论如何,我们都应该追求编写优雅、易读的代码,因为这样可以提高我们的开发效率和代码质量,也可以让我们的代码更容易被他人理解和接受。希望这篇博客对你有帮助