一个好的前端开发人员必须掌握的前端代码整洁与开发技巧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>
目录
相关文章
|
10天前
|
前端开发 JavaScript API
(前端3D模型开发)网页三维CAD中加载和保存STEP模型
本文介绍了如何使用`mxcad3d`库在网页上实现STEP格式三维模型的导入与导出。首先,通过官方教程搭建基本项目环境,了解核心对象如MxCAD3DObject、Mx3dDbDocument等的使用方法。接着,编写了加载和保存STEP模型的具体代码,包括HTML界面设计和TypeScript逻辑实现。最后,通过运行项目验证功能,展示了从模型加载到保存的全过程。此外,`mxcad3d`还支持多种其他格式的三维模型文件操作。
|
29天前
|
缓存 前端开发 JavaScript
利用代码分割优化前端性能:策略与实践
在现代Web开发中,代码分割是提升页面加载性能的有效手段。本文介绍代码分割的概念、重要性及其实现策略,包括动态导入、路由分割等方法,并探讨在React、Vue、Angular等前端框架中的具体应用。
|
1月前
|
监控 前端开发 JavaScript
前端工程化和传统前端开发的区别是什么?
前端工程化相比传统前端开发,在开发模式、代码组织与管理、构建与部署流程、团队协作、性能优化以及技术选型等方面都有了显著的改进和提升,能够更好地应对现代前端应用开发的复杂性和高要求。
|
2天前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
22 3
|
18天前
|
缓存 监控 前端开发
探索前端性能优化:关键策略与代码实例
本文深入探讨前端性能优化的关键策略,结合实际代码示例,帮助开发者提升网页加载速度和用户体验,涵盖资源压缩、懒加载、缓存机制等技术。
|
1月前
|
Web App开发 缓存 监控
前端性能优化实战:从代码到部署的全面策略
前端性能优化实战:从代码到部署的全面策略
27 1
|
1月前
|
Web App开发 前端开发 JavaScript
前端性能优化实战:从代码到部署的全面指南
前端性能优化实战:从代码到部署的全面指南
31 1
|
1月前
|
前端开发 JavaScript
前端界的革命:掌握这些新技术,让你的代码简洁到让人惊叹!
前端技术的快速发展带来了许多令人惊叹的新特性。ES6及其后续版本引入了箭头函数、模板字符串等简洁语法,极大减少了代码冗余。React通过虚拟DOM和组件化思想,提高了代码的可维护性和效率。Webpack等构建工具通过模块化和代码分割,优化了应用性能和加载速度。这些新技术正引领前端开发的革命,使代码更加简洁、高效、可维护。
26 2
|
29天前
|
缓存 监控 前端开发
前端性能优化:从代码到部署的全面策略
前端性能优化:从代码到部署的全面策略
|
2月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
178 2
下一篇
DataWorks