代码不规范,同事两行泪,作为前端,如何让自己的代码更优雅?


前言

前端开发是一个涉及多种技术和语言的领域,如 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
  • 目录命名:全部采用小写方式,以中划线分隔,有复数结构时,要采用复数命名法,缩写不用复数,如 componentsassets
  • 文件命名:全部采用小写方式,以中划线分隔,如 index.htmlmain.jsstyle.css
  • 变量命名:采用小写驼峰命名法(lowerCamelCase),即第一个单词首字母小写,后面单词首字母大写,如 userNameisLogin
  • 常量命名:全部大写,单词间用下划线隔开,如 MAX_LENGTHAPI_URL
  • 函数命名:采用小写驼峰命名法(lowerCamelCase),并且要能体现函数的功能或作用,如 getDatahandleClick
  • 类命名:采用大写驼峰命名法(UpperCamelCase),即每个单词首字母都大写,如 UserProduct
  • 组件命名:采用大写驼峰命名法(UpperCamelCase),并且使用完整单词而不是缩写,如 HeaderFooter
  • ts类型命名:采用大写驼峰命名(UpperCamelCase),并且加上类型前缀,如接口(interface)命名 IStateIUserInfo
  • 请求接口命名:采用req前缀+大写驼峰命名(UpperCamelCase),如 reqGetUserInforeqGetUserList

总结

以上就是我对前端开发过程中,让代码更优雅、更容易读的方法的一些总结和建议。当然,这些方法并不是一成不变的,也不是唯一正确的。不同的项目和团队可能有不同的需求和风格。但是我认为,无论如何,我们都应该追求编写优雅、易读的代码,因为这样可以提高我们的开发效率和代码质量,也可以让我们的代码更容易被他人理解和接受。希望这篇博客对你有帮助

猜你喜欢

转载自blog.csdn.net/wz9608/article/details/128967401