一个好的前端开发人员必须掌握的前端代码整洁与开发技巧2

简介: 一个好的前端开发人员必须掌握的前端代码整洁与开发技巧

1.16 链判断运算符

编程实务中,如果读取对象内部的某个属性,往往需要判断一下,属性的上层对象是否存在。比如,读取message.body.user.firstName这个属性,安全的写法是写成下面这样。

// 错误的写法
const  firstName = message.body.user.firstName || 'default';
// 正确的写法
const firstName = (message
  && message.body
  && message.body.user
  && message.body.user.firstName) || 'default';
// 但是这种写法如果层级过长会显得冗长,可读性也不强,这是我们可以利用链判断运算符来解决
//链判断运算符写法
const firstName = message?.body?.user?.firstName || 'default';

链判断运算符?.有三种写法。

  • obj?.prop // 对象属性是否存在
  • obj?.[expr] // 同上 也可以理解为 arr?.[index]
  • func?.(...args) // 函数或对象方法是否存在

下面是?.运算符常见形式,以及不使用该运算符时的等价形式。

a?.b
// 等同于
a == null ? undefined : a.b
a?.[x]
// 等同于
a == null ? undefined : a[x]
a?.b()
// 等同于
a == null ? undefined : a.b()
a?.()
// 等同于
a == null ? undefined : a()

常规:

// 计划 id
let planId = this.ticketDetail && this.ticketDetail.planDetailVoList && this.ticketDetail.planDetailVoList[0] && this.ticketDetail.planDetailVoList[0].planId 

简写:

// 计划 id
let planId = this.ticketDetail?.planDetailVoList?.[0]?.planId 
// 如果任意一个问号前面的值为null或者undefined都将直接返回undefined,不在向下取值

注意:链判断运算符只能在js代码块中使用,不能在template里面的标签上使用,否则会解析报错,如果想要在template里达到上述简写效果可以在计算属性中使用。


// 错误的写法
<template>  
    <div class="wrap">   
        <span>计划编号:</span>
        {{
              ticketDetail && ticketDetail.planDetailVoList && ticketDetail.planDetailVoList[0] && ticketDetail.planDetailVoList[0].planNo || ''
        }} 
  </div> 
</template>
<script> 
    export default {  
        data() {    
            return {
                ticketDetail: {
                    planDetailVoList: [
                        {
                            planNo: 'T202304200940' // 计划编号
                        }
                    ]
                } 
            }  
        }
    } 
</script>
//正确的写法
<template>  
    <div class="wrap">   
        <span>计划编号:</span>
        {{ planNo }} 
  </div> 
</template>
<script> 
    export default {  
        data() {    
            return {
                ticketDetail: {
                    planDetailVoList: [
                        {
                            planNo: 'T202304200940' // 计划编号
                        }
                    ]
                } 
            }  
        },
        // 计算属性
        computed: {
            // 计划编号
            planNo({ticketDetail}) {
               return ticketDetail?.planDetailVoList?.[0]?.planNo || ''
            }
        }
    } 
</script>

链判断运算符知识点链接:https://es6.ruanyifeng.com/#docs/operator

1.17 Null 判断运算符

读取对象属性的时候,如果某个属性的值是null或undefined,有时候需要为它们指定默认值。常见做法是通过||运算符指定默认值。

const headerText = response.settings.headerText || 'Hello, world!';
const animationDuration = response.settings.animationDuration || 300;
const showSplashScreen = response.settings.showSplashScreen || true;

上面的三行代码都通过||运算符指定默认值,但是这样写是错的。开发者的原意是,只要属性的值为null或undefined,默认值就会生效,但是属性的值如果为空字符串或false或0,默认值也会生效。

为了避免这种情况,ES2020 引入了一个新的 Null 判断运算符??。它的行为类似||,但是只有运算符左侧的值为null或undefined时,才会返回右侧的值。

const headerText = response.settings.headerText ?? 'Hello, world!';
const animationDuration = response.settings.animationDuration ?? 300;
const showSplashScreen = response.settings.showSplashScreen ?? true;

上面代码中,默认值只有在左侧属性值为null或undefined时,才会生效。

1.18 逻辑运算符

使用逻辑运算符!! 快速进行布尔转换。

常规:

// 判断是否是ios环境
const isIOS = Boolean(window.navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/))

简写:

// 判断是否是ios环境
const isIOS = !!window.navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)

1.19 扩展运算符

使用扩展运算符进行数组、对象合并。

常规:

let obj = { name: 'zhangsan', sex: '男' }
obj = Object.assign(obj, {age: 18})
let arr = ['zhangsan', 'lisi']
arr = arr.concat(['wangwu', 'zhaoliu'])

简写:

let obj = { name: 'zhangsan', sex: '男' }
obj = {...obj, ...{age: 18}}
obj = {...obj, age: 18}
let arr = ['zhangsan', 'lisi']
arr = [...arr, ...['wangwu', 'zhaoliu']]

1.20 +运算符隐式转换

使用+运算符不仅可以将字符串转为数字,还可以将时间转为时间戳。

常规:

let type = '1'
type = Number(type)
let sjc = new Date().getTime()

简写:

let type = '1'
type = +type
let sjc = +new Date()

1.21 v-for中使用解构

常规:

<li  v-for="item in users"  :key="item.id" >  {{ item.name }} </li> 

简写:

<li  v-for="{ name, id } in users"  :key="id" >  {{ name }} </li> 

1.22 使用Set给数组去重

常规:

Array.prototype.distinct = function(){
    let arr = this,
      result = [],
      i,
      j,
      len = arr.length;
    for(i = 0; i < len; i++){
      for(j = i + 1; j < len; j++){
        if(arr[i] === arr[j]){
          j = ++i;
        }
      }
      result.push(arr[i]);
     }
     return result;
}
const arra = [1,2,3,4,4,1,1,2,1,1,1];
arra.distinct();  // [3,4,2,1]

简写:

const arr = [1, 1, 2, 3, 4, 4];
const uniqueArr = [...new Set(arr)];
const uniqueArr1 = Array.from(new Set(arr)); // [1,2,34]

1.23 Object[key] 重用代码块

常规:

function validate(values) {
    if(!values.first) {
        uni.showToast({
           title: '第一项不可为空',
           icon: 'none'
        })
        return false
    }
    if(!values.last) {
        uni.showToast({
           title: '最后一项不可为空',
           icon: 'none'
        })
        return false
    }
    return true
}
let isCheckPass = validate({first:'', last: ''})
console.log('是否检验通过', isCheckPass)

简写:

// 对象校验规则
const schema = {
    first: {
        required: true,
        failedTip: '第一项不可为空'
    },
    last: {
        required: true,
        failedTip: '最后一项不可为空'
    }
}
// 通用校验函数
const validate = (schema, values) => {
    for(field in schema) {
        if(schema[field].required) {
            if(!values[field]) {
                uni.showToast({
                   title: schema[field].failedTip,
                   icon: 'none'
                })
                return false
            }
        }
    }
    return true
}
let isCheckPass = validate(schema, {first: '1', last: '3'})
console.log('是否检验通过', isCheckPass)

1.24 禁用不必要的嵌套块

常规:

function submitTicket(){
    const { ticketCode, isDoubleSign } = this
    if(ticketCode === '05') {
        if(isDoubleSign) {
            this.signType = '02'
        }
    }
}

简写:

function submitTicket(){
    const { ticketCode, isDoubleSign } = this
    if(ticketCode === '05' && isDoubleSign) {
      this.signType = '02'
    }
}

1.25 具有默认值的函数参数应该放到最后

默认值放到最后可以让函数少传实参还能正常执行,收获预期结果。

常规:

求和函数,把具有默认值的参数放在参数列表「左边」


function sum(a = 10, b) {
    return a + b
}
/*
  第1个实参 总是对应 第1个形参
  所以,3 赋值给 a, 替换掉默认值 10
  参数b没有传值,最终函数返回NaN
*/  
sum(3) // returns NaN as b is undefined

简写:

求和函数,把具有默认值的参数放在参数列表「右边」

function sum(b,a = 10) {
    return a + b
}
/*
  3 赋值给 b
  a 没有传值,使用默认值 10
*/
sum(3) // 13

1.26 组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法

Bad Code

<template>  
    <div class="wrap">   
        <span>工作负责人:</span>
        {{
              planDetail.personInfo.name + (planDetail.personInfo.phone? '-' +    planDetail.personInfo.phone : 'planDetail.personInfo.phone')
        }} 
  </div> 
</template>
<script> 
    export default {  
        data() {    
            return {
                planDetail: {
                    personInfo: {
                        name: 'zhangsan',
                        phone: '15236616216'
                    }   
                } 
            }  
        }
    } 
</script>

Good Code

<template>  
    <div class="wrap">   
        <span>工作负责人:</span>
        {{
             WorkLeader
        }} 
  </div> 
</template>
<script> 
    export default {  
        data() {    
            return {
                planDetail: {
                    personInfo: {
                        name: 'zhangsan',
                        phone: '15236616216'
                    }   
                },
            }  
        },
        conputed: {
            // 复杂的表达式则应该重构为计算属性
            WorkLeader({planDetail}) {
                return planDetail.personInfo.name + (planDetail.personInfo.phone? '-' +         planDetail.personInfo.phone : planDetail.personInfo.phone)
            }
        }
    } 
</script>

注意:计算属性中必须包含return字段,且不能产生副作用(如修改外部变量,调用外部无关方法操作了dom等等)

1.27 计算属性使用解构赋值减少this滥用,提升性能

Bad Code

<script> 
export default {  
    data() {    
        return {      
            ticketDetail: {
                wtType: '03'
            },
            sendFlag: false,
            provPermitType: ''
        }  
    },  
    computed: { 
        // 票类型
        wtType() {
            return this.ticketDetail.wtType
        },
        // 应采取安全措施是否可编辑
        measureEdit() { 
            // 配一工作票 非远程许可 非发送  可编辑
            if (this.ticketDetail.wtType === "03" && !this.sendFlag && !['01', '02'].includes(this.provPermitType)) {
                return true
            }
            return false
        }
    }
} 
</script>

上述计算属性中存在滥用this去读取data数据的问题 , 使用this去读取data中数据时会去收集依赖,如果滥用this去读取data中数据,会多次重复地收集依赖,从而产生性能问题。

解决办法:

计算属性的值是一个函数,其参数是Vue的实例化this对象,在上述计算属性中滥用this的例子中可以这样优化。

Good Code


<script> 
export default {  
    data() {    
      return {      
            ticketDetail: {
                wtType: '03'
            },
            sendFlag: false,
            provPermitType: ''
        }  
    },  
    computed: { 
        // 票类型
        wtType({ticketDetail}) {
            return ticketDetail.wtType
        },
        // 应采取安全措施是否可编辑
        measureEdit({wtType, sendFlag, provPermitType}) { 
            // 配一工作票 非远程许可 非发送  可编辑
            if (wtType === "03" && !sendFlag && !['01','02'].includes(provPermitType)) {
                return true
            }
            return false
        }
    }
} 
</script>
目录
相关文章
|
JSON 监控 前端开发
AMIS:百度开源的前端低代码神器,18.4k star 背后的开发效率提升利器
AMIS(前端低代码框架)是百度开源的低代码前端框架,基于纯 JSON 配置即可生成完整后台页面,包括表单、表格、图表、CRUD 列表,支持可视化拖拽编辑。,星标数已达 18.4k,百度内部已沉淀超过 5 万个页面,广泛应用于审核系统、数据管理后台、模型监控等落地场景
2007 0
|
人工智能 前端开发 JavaScript
前端工程化演进之路:从手工作坊到AI驱动的智能化开发
前端工程化演进之路:从手工作坊到AI驱动的智能化开发
1119 19
前端工程化演进之路:从手工作坊到AI驱动的智能化开发
|
人工智能 自然语言处理 前端开发
DeepSite:基于DeepSeek的开源AI前端开发神器,一键生成游戏/网页代码
DeepSite是基于DeepSeek-V3模型的在线开发工具,无需配置环境即可通过自然语言描述快速生成游戏、网页和应用代码,并支持实时预览效果,显著降低开发门槛。
2231 93
DeepSite:基于DeepSeek的开源AI前端开发神器,一键生成游戏/网页代码
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
853 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
存储 消息中间件 前端开发
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
校园圈子系统校园论坛小程序采用uni-app前端框架,支持多端运行,结合PHP后端(如ThinkPHP/Laravel),实现用户认证、社交关系管理、动态发布与实时聊天功能。前端通过组件化开发和uni.request与后端交互,后端提供RESTful API处理业务逻辑并存储数据于MySQL。同时引入Redis缓存热点数据,RabbitMQ处理异步任务,优化系统性能。核心功能包括JWT身份验证、好友系统、WebSocket实时聊天及活动管理,确保高效稳定的用户体验。
908 4
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
|
自然语言处理 前端开发 IDE
用通义灵码全新智能体+MCP实现从设计稿到前端代码,个人免费用
通义灵码全新升级,发布国内首个支持“自主决策+工具链闭环”的编程智能体,面向个人免费!新增功能包括智能体模式、混合推理模型Qwen3支持、全面集成MCP中文社区(涵盖2400+服务)及长期记忆能力。用户可通过IDE插件使用,兼容主流开发环境如JetBrains、VS Code和Visual Studio。教程展示如何将MasterGo设计稿转化为前端代码,简化开发流程。探索链接:[通义灵码官网](https://lingma.aliyun.com/)。
|
JSON 前端开发 数据可视化
前端开发者狂喜!30K star开源组件库,界面美观度/开发速度双碾压!
嗨,大家好,我是小华同学。Layui 是一款开源前端 UI 组件库,具有极简设计、强大功能和卓越性能,支持布局、表单、表格、弹层等六大模块,组件高度可定制。它无需复杂构建工具,直接面向浏览器开发,极大提升开发效率与界面美观度。适合新手和老手,快来试试吧!
979 0
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
1775 14
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
1160 0

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1435
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    712
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    568
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    574
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    662
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    841
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1646
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    396
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1362
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    672