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方案直接减少了代码量,且代码更清晰;
文章太长了,就不在这放源码了。
github源码地址:https://github.com/cwlch/jsutil/blob/release/src/tools/create-dicts.ts
giteee地址:https://gitee.com/cwl_ch/jsutil/blob/release/src/tools/create-dicts.ts
github源码地址:https://github.com/cwlch/jsutil/blob/release/src/tools/create-dicts.ts
giteee地址:https://gitee.com/cwl_ch/jsutil/blob/release/src/tools/create-dicts.ts
本篇文章中的方法已发布在Jsutil库中,该库为一个功能性的函数库,欢迎大家引用及Star或者提出宝贵的意见。