JS对象扩展成key,value都能访问成员属性,操作字典表数据更便捷 ——Jsutil类

日常开发中我们经常会碰到一些状态数据管理的场景,针对这种场景封装了一个可以根据属性查询成员的对象方;
 
后管做得多的小伙伴,应该会经常遇到下图的场景:

 
遇到这个场景不知大家第一想法是怎么做呢?
 
比较好的方案是:可以用Object实现,类似枚举;
还有人可能觉得:用数组包对象,做一个类似字典表管理的意思;(这个方法就不适用,不信的可以去试试,文章里就不贴代码了)
 
我们看看使用Object实现有些什么缺陷:
<template>
<select >
//A处需要展示所有状态进行筛选,我们这可以取巧直接循环对象;
    <option v-for="(item, index) in STATUS" :value="index">{{item}}</option>
<select/>
<table>
    <tr v-for="row in data">       
        //B处需要可以直接取值,这里是最方便的;
        <td>{{STATUS[row.status]}}</td>
        <td>
        //C处需跟进状态显示不同操作面板,这时候需要判断,就不友好了,得直接判断数字,STATUS根本就没用。
            <button v-if="row.status === 100" @click="xx">上传中的操作</button>
            <button v-else-if="row.status === 200" @click="xx">上传完成,审核的操作</button>
            <button v-else-if="row.status === 300" @click="xx">审核完的操作</button>
        </td>
    </tr>
</table>
</template>
<script setup>
import {STATUS} from 'dicts.js'
const data = [{order:'订单巴拉',status:100},{order:'订单巴拉222',status:200}]
</script>

//dicts.js
<script>
export const STATUS = {
    100 : '上传中',
    200 : '审核中',
    300 : '已完成'
}
</script>
 
此时我们看到上面代码的第三处业务,STATUS是覆盖不到的,而且出现了魔法数字。
 
我们可以使用以下方法改进:
...
    //A处选择下拉框业务
    <option v-for="(item, index) in STATUS" :value="index">{{item}}</option>
    ...
    //B处,展示状态描述中文  这里你就会发现使用value属性可以直接反向取到中文描述的       
        <td>{{STATUS[row.status]}}</td>
        ...
        //C处业务,显示不同操作面板还是需要判断,但不会再出现数字
            <button v-if="row.status === STATUS_VAL.UPLOADING" @click="xx">等待中的操作</button>
            <button v-else-if="row.status === STATUS_VAL.EXAMINE" @click="xx">进行种的操作</button>
            <button v-else-if="row.status === STATUS_VAL.FINISH" @click="xx">已完成的操作</button>
        ....
<script setup>
import {STATUS, STATUS_VAL} from 'dicts.js'
const data = [{order:'订单巴拉',status:100},{order:'订单巴拉222',status:200}]
</script>

//dicts.js
<script>
export const STATUS_VAL = {
    UPLOADING : 100,
    EXAMINE : 200,
    FINISH : 300
}
export const STATUS = {
    [STATUS_VAL.UPLOADING] : '上传中',
    [STATUS_VAL.EXAMINE] : '审核中',
    [STATUS_VAL.FINISH] : '已完成'
}
</script>
1、我们发现代码改进后确实解决了魔法数字的问题,但会导致我需要导入导出多个变量。
2、如果维护的状态数据多,这就会是一个很操蛋的写法了(要记的变量名太多,import的变量就占好多行)。
 
如果想要满足这种通过key和value都能访问对象成员属性的场景,JS本身是没法支持的;
 
所以我封装了一个比较契合的方法:
 
来看看封装好的_CreateDicts方法怎么实现

...
    //A处选择下拉框业务
    <option v-for="item in options" :value="item.value">{{item.label}}</option>
    ...
    //B处,展示状态描述中文  这里你就会发现使用value属性可以直接反向取到中文描述的       
        <td>{{STATUS[row.status].label}}</td>
        ...
        //C处业务,显示不同操作面板还是需要判断,但不会再出现数字
            <button v-if="row.status === STATUS.UPLOADING.value" @click="xx">等待中的操作</button>
            <button v-else-if="row.status === STATUS.EXAMINE.value" @click="xx">进行种的操作</button>
            <button v-else-if="row.status === STATUS.FINISH.value" @click="xx">已完成的操作</button>
        ....
<script setup>
import {STATUS} from 'dicts.js';

//STATUS 实例是返回的对象,需要变量数组时可以通过方法获取到数组
const options = STATUS.getArray();

const data = [{order:'订单巴拉',status:100},{order:'订单巴拉222',status:200}]
</script>

//dicts.js
<script>
//jsutil._CreateDicts是封装好的方法,
export const STATUS = jsutil._CreateDicts({
    'UPLOADING' : [100, '等待中'],
    'EXAMINE' : [200,  '进行中' ],
    'FINISH' : [ 300,  '已完成' ]
});
</script>
 
方法的具体说明:
 
  传参数说明:接收的参数必须是对象,对象成员可以是:对象,数组;
 
1、对象成员参数
//这种是最直观的,就是一个正常的对象,但他可以通过对象种的value值拿到其他属性,且key也回成为其成员的key属性
let a = jsutil._CreateDicts({
    finish : {value:300,label:'完成',name:'名字',other:'其他'}
})
//通过key拿值
a.finish.value //300
a.finish.label //完成
a.finish.name //名字
a.finish.key //finish
//通过value拿值
a[300].value //300
a[300].value //300
a[300].name //名字
a[300].key //finish
//通过其他属性是拿不到值的;
 
2、数组成员参数
//成员是数组的话,
// 数组第一位为value,
// 第二位为label,
// 第三位就是一个对象,其他的扩展字段
let a = jsutil._CreateDicts({
    testMore : [200,'进行种',{name:'测试名字',other:'其他'}]
    finish : [300,'完成',{name:'测试名字2',other:'其他2'}]
})
//通过key拿值
a.finish.value //300
a.finish.label //完成
a.finish.name //名字
a.finish.key //finish
//通过value拿值
a[300].value //300
a[300].value //300
a[300].name //名字
a[300].key //finish
 
3、  value值可以为Boolean值
let a = jsutil._CreateDicts({
    show : [true,'显示'],
    hide : [false,'隐藏']
})
//通过key拿值
a.show.value //true
a.show.label //显示
//通过value拿值
a[true].value //true
a[true].label //隐藏
1、封装此方法主要用于状态管理场景使用
2、在业务代码中不会出现魔法数字;
3、相对对比Object方式,可以维护多个成员属性;
4、相对使用Object方案直接减少了代码量,且代码更清晰;
 
 
本篇文章中的方法已发布在Jsutil库中,该库为一个功能性的函数库,欢迎大家引用及Star或者提出宝贵的意见。

posted @ 2022-11-21 23:23  灰色的蓝猫  阅读(336)  评论(0编辑  收藏  举报