【提高代码可读性】—— 手握多个代码优化技巧、细数哪些惊艳一时的策略

d639cc6017f841ecba1392933efc2418.gif

回顾  前期  89a5d93bcce94f7cbe42539567637cb3.gif

趁着下班前五分钟书写——Vue3通讯(常规写法、语法糖、v-modle、兄弟通讯)_0.活在风浪里的博客-CSDN博客Vue3 组件通讯https://blog.csdn.net/m0_57904695/article/details/128145150?spm=1001.2014.3001.5501

3f8b2aaa929d4f63924271586bce3414.gif

目录

一、可选链接运算符【?.】

二、空值合并操作符【??】

 三、提升代码可读性,减少 if-else 几个小技巧 ☠

三一、对象配置/策略模式📑 【重要 好用】

例一:根据不同的用户使用不同的折扣,如:普通用户不打折,普通会员用户9折,年费会员8.5折,超级会员8折

例二:绩效为A的人年终奖有4倍工资,绩效为B的有3倍,绩效为C的只有2倍。

例三: 复杂分支优化

 例四:抽离分支优化:【建议!】

 例五:模块抽离例子

四、Vue3 setup设置name

结语: 


67516d17777046f9beb4d3c0eb9076c9.png

一、可选链接运算符【?.】

左面值不是null 和 undefined,就执行右面的值(拼接上左面)

不使用 可选链接运算符

if (data && data.children && data.children[0] && data.children[0].title) {
    // I have a title!
}

使用后

let title = data?.children?.[0]?.title;

对于静态属性用法是:

object?.property

对于动态属性将其更改为:

object?.[expression] 

 对于方法的调用你可以这样写

object.runsOnlyIfMethodExists?.()

举例:

let parent = {
    name: "parent",
    friends: ["p1", "p2", "p3"],
    getName: function() {
      console.log(this.name)
    }
  };
  
  parent.getName?.()   // parent
  parent.getTitle?.()  //不会执行

二、空值合并操作符【??】

空值合并操作符(??)是一个逻辑操作符,
当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。

console.log(null ?? 666)   
console.log(undefined ?? 666)
// 以上输出结果都为666

 ?? 与 || 的区别

One ?? Two
One || Two

相同点:
?? 和 || 的语法相同。

不同点:

判断的方法不同:
使用 ?? 时,只有One为 null 或者 undefined 时才会返回 two;
使用 || 时,One会先转化为布尔值判断,为true时返回One , false 返回Two,

若左边能转成true,返回左边式子的值,反之返回右边式子的值;

简单来说就是优先返回true的值


 // ??
  undefined ?? 2    // 2
  null ?? 2        // 2
  0 ?? 2            // 0
  "" ?? 2            // ""
  true ?? 2        // true
  false ?? 2        // false


 // ||
  undefined || 2    // 2
  null || 2        // 2
  0 || 2            // 2
  "" || 2            // 2
  true || 2        // true
  false || 2        // 2

顺便记录下转布尔值的两种方法 

方法一:使用 双重逻辑非  !!,语法: !!要转换的值 Boolean( "100001356145")  //true

方法二:使用Boolean()函数,可以强制把值转换为布尔值,语法 :Boolean(字符串) !! Objec //true


 三、提升代码可读性,减少 if-else 几个小技巧 ☠

 使用 if else

let c
if(a){
    c = a
} else {
    c = b
}

使用 || 短路运算符 (会先转换为布尔值,若左边能转成true,返回左边式子的值,反之返回右边式子的值) 

let c = a || b

例:有A、B、C、D四种种类型,在A、B的时候输出1,C输出2、D输出3,默认输出0。

let type = 'A'

//if else if
if (type === 'A' || type === 'B') {
    console.log(1);
} else if (type === 'C') {
    console.log(2);
} else if(type === 'D') {
    console.log(3);
} else {
    console.log(0)
}

//switch case
switch (type) {
    case 'A':
    case 'B':
        console.log(1)
        break
    case 'C':
        console.log(2)
        break
    case 'D':
        console.log(3);
        break;
    default:
        console.log(0)
}

三一、对象配置/策略模式📑 【重要 好用】

接下来我们用对象配置的方法实现一下上述的例子

let type = 'A'

let tactics = {
    'A': 1,
    'B': 1,
    'C': 2,
    'D': 3,
    default: 0
}
console.log(tactics[type]) // 1

接下来用几个例子让大家更加熟悉一点。

例一:根据不同的用户使用不同的折扣,如:普通用户不打折,普通会员用户9折,年费会员8.5折,超级会员8折

先使用 if else 实现😢

// 获取折扣 --- 使用if else
const getDiscount = (userKey) => {
    if (userKey === '普通会员') {
        return 0.9
    } else if (userKey === '年费会员') {
        return 0.85
    } else if (userKey === '超级会员') {
        return 0.8
    } else {
        return 1
    }
}
console.log(getDiscount('普通会员')) // 0.9

在 使用对象配置/策略模式实现🙂

// 获取折扣 -- 使用对象配置/策略模式
const getDiscount = (userKey) => {
    // 我们可以根据用户类型来生成我们的折扣对象
    let discounts = {
        '普通会员': 0.9,
        '年费会员': 0.85,
        '超级会员': 0.8,
        'default': 1
    }
 // 如果左边值转换布尔值后为true就返回左边,否则反之 
    return discounts[userKey] || discounts['default']
}
console.log(getDiscount('普通会员')) // 0.9

从上面的案列中可以明显看得出来,使用对象配置比使用if else可读性更高,后续如果需要添加用户折扣也只需要修改折扣对象就行👍


对象配置不一定非要使用对象去管理我们键值对,还可以使用 Map去管理🦋,如:

// 获取折扣 -- 使用对象配置/策略模式
const getDiscount = (userKey) => {
    // 我们可以根据用户类型来生成我们的折扣对象
    let discounts = new Map([
        ['普通会员', 0.9],
        ['年费会员', 0.85],
        ['超级会员', 0.8],
        ['default', 1]
    ])
    return discounts.get(userKey) || discounts.get('default')
}
console.log(getDiscount('普通会员')) // 0.9

例二:绩效为A的人年终奖有4倍工资,绩效为B的有3倍,绩效为C的只有2倍。

const calculateBonus = (performanceLevel, salary) => { 
    if (performanceLevel === 'A'){
        return salary * 4
    }
    if (performanceLevel === 'B'){
        return salary * 3
    }
    if (performanceLevel === 'C'){
        return salary * 2
    }
}
calculateBonus( 'B', 20000 ) // 输出:60000

完成了,但是如果增加了一种新的 绩效等级D,或者把 A等级的倍数改成5,那我们必须阅读所有代码才能去做修改

所以我们可以用对象配置/策略模式去简化这个函数😺

let state = new Map([
    ['A', 4],
    ['B', 3],
    ['C', 2]
])

const hCalc = (type, money) => { 
    return state.get(type) * money
}

 hCalc( 'B', 20000 ) // 输出:60000

例三: 复杂分支优化

function getUserDescribe(name) {
    if (name.length > 3) {
        console.log("名字太长");
    } else if (name.length < 2) {
        console.log("名字太短");
    } else if (name[0] === "陈") {
        console.log("小陈");
    } else if (name[0] === "李" && name !== "李鹏") {
        console.log("小李");
    } else if (name === "李鹏") {
        console.log("管理员");
    } else {
        console.log("此人比较神秘!");
    }
}

优化后;

function getUserDescribe(name) {
    const describeForNameMap = [
        [
            (name) => name.length > 3, // 判断条件
            () => console.log("名字太长") // 执行函数
        ],
        [
            (name) => name.length < 2, 
            () => console.log("名字太短")
        ],
        [
            (name) => name[0] === "陈", 
            () => console.log("小陈")
        ],
        [
            (name) => name === "大鹏", 
            () => console.log("管理员")
        ],
        [
            (name) => name[0] === "李" && name !== "李鹏",
            () => console.log("小李"),
        ],
    ];
    // 获取符合条件的子数组
    const getDescribe = describeForNameMap.find((item) => item[0](name));
    // 子数组存在则运行子数组中的第二个元素(执行函数)
    getDescribe ? getDescribe[1]() : console.log("此人比较神秘!");
}

 例四:抽离分支优化:【建议!】

const describeForNameMap = {
    小刘: () => console.log("刘哥哥"),
    小红: () => console.log("小红妹妹"),
    陈龙: () => console.log("大师"),
    李龙: () => console.log("师傅"),
    大鹏: () => console.log("恶人"),
};

function getUserDescribe(name) {
    describeForNameMap[name] ? describeForNameMap[name]() : console.log("此人比较神秘!");
}

优化后:

const describeForNameMap = [
    [
        (name) => name.length > 3, // 判断条件
        () => console.log("名字太长") // 执行函数
    ],
    [
        (name) => name.length < 2, 
        () => console.log("名字太短")
    ],
    [
        (name) => name[0] === "陈", 
        () => console.log("小陈")
    ],
    [
        (name) => name === "大鹏", 
        () => console.log("管理员")
    ],
    [
        (name) => name[0] === "李" && name !== "李鹏",
        () => console.log("小李"),
    ],
];
    
function getUserDescribe(name) {
      // 通过find方法找到子数组中的第一个函数(判断条件)为true的子数组
    const getDescribe = describeForNameMap.find((item) => item[0](name));
    // 子数组存在则运行子数组中的第二个元素(执行函数)
    getDescribe ? getDescribe[1]() : console.log("此人比较神秘!");
}

通过模块化的开发也可以将这个map对象写进一个单独的js文件,之后在需要使用的地方导入即可。 

 例五:模块抽离例子

/**
* @method getUserDescribe
* @param name 用户名
* @param uUser 用户账号
* @description 根据用户名和用户账号获取用户头像
* @returns {string} 用户头像
* @author zk
* @createDate 2023/03/02 15:06:40
* @lastFixDate 2023/03/02 15:06:40
*/
export function getUserDescribe(name: string, uUser: string, userImg: {value:string})
{
    const describeForNameMap = [
        [
            () => name == '监管' && uUser.indexOf('yanghang') === -1, // 判断条件
            () => (userImg.value = '/user5.png'), // 执行函数
        ],
        [() => uUser.indexOf('jianguan') > -1, () => (userImg.value = '/user5.jpg')],
        [() => uUser.indexOf('dianjunqu') > -1, () => (userImg.value = '/user4.jpg')],
        [() => uUser.indexOf('yinhang') > -1, () => (userImg.value = '/user3.png')],
        [() => uUser.indexOf('yanghang') > -1, () => (userImg.value = '/user6.png')],
    ];
    // 通过find方法找到子数组中的第一个函数(判断条件)为true的子数组
    let getDescribe = describeForNameMap.find((item) => item[0]());
    console.log('!这里输出 🚀 ==>:', getDescribe);
    // 子数组存在则运行子数组中的第二个元素(执行函数)
    getDescribe ? getDescribe[1]() : (userImg.value = '/user1.png');
}


// 使用 
 1:import { getUserDescribe } from '/@/utils/userImg';
 2:getUserDescribe(name, uUser, userImg);

四、Vue3 setup设置name

 vue3 中使用 setup 语法时,指定 name 属性有三种方式,个人推荐最后一种方式。

方式1:传统方式

传统方式是使用 defineComponent() 方法定义组件,通过对象形式设置 name 属性和 setup 函数传递给该方法。代码如下:

<template>
  <div>
    Test, {{str}}
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'

export default defineComponent({
  name: 'Test',
  setup: () => {
    const str = ref('hello')
    return {
      str
    }
  }
})
</script>

方式2:两个 script 标签

这种方式与传统方式类似,只是在传统方式的基础上,将 setup 提取到另一个标签中。代码如下:


<template>
  <div>
    Test, {{str}}
  </div>
</template>

<script lang="ts" setup>
import { defineComponent, ref } from 'vue'
const str = ref('hello')
</script>

<script lang="ts">
export default defineComponent({
  name: 'Test'
})
</script>

这种方式在 webstorm 中写起来很不顺手,webstorm 总是自动合并两个 script 标签中的代码。

方式3:优雅的方式

这种方式个人最推荐,首先安装配置插件,之后在 script 标签上指定 name 属性即可,一劳永逸。

安装插件 vite-plugin-vue-setup-extend,该插件的作用就是使 vue script setup 语法支持 name 属性。


yarn add vite-plugin-vue-setup-extend -D

 vite.config.ts 中配置插件:

import vueSetupExtend from 'vite-plugin-vue-setup-extend';


export default defineConfig({
  plugins: [
    ...
    vueSetupExtend(),
    ...
  ],
  ...
})

完成插件的配置后,便可以在 script 标签上指定 name 属性:


<template>
  <div>
    Test, {{str}}
  </div>
</template>

<script lang="ts" setup name="Test">
import { ref } from 'vue'
const str = ref('hello')
</script>

这种方式需要特别注意,如果 script标签中内容为空时,name 属性就无法加载。一定要确保 script 标签内一定要有内容,哪怕是一行注释也行:

<script lang="ts" setup name="Test">// ...</script>

结语: 

本文到这里就要完结了,感谢你的阅读!再见,

5e027d9c222c44d088515002e4617e30.gif

                                                               分享快乐,留住感动. '2022-012-29 14:40:22' --活在分浪里

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彩色之外

你的打赏是我创作的氮气加速动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值