常量和枚举

11/1/2022

# 一、背景与问题

如果你是全栈开发者,你应该了解服务端语言的枚举类型enum,但是对于前端而言没有枚举类型。如果你是前端开发者,你一定见过这样的代码:

    // 根据数字获取文件位置描述
    getFileLocationTypeDesc(value) {
      if(value === 1){
        return "本地文件服务";
      }
      if(value === 3){
        return "阿里OSS文件服务";
      }
      if(value === 3){
        return "七牛文件服务";
      }
    },
1
2
3
4
5
6
7
8
9
10
11
12
<div>
  <span v-if="locationType === 2">
    <input type="file"/>
  </span>
  <span v-if="locationType === 3">
    <button value="上传"/>
  </span>
</div>
1
2
3
4
5
6
7
8

如果后端把value的值修改一种类型或者新加一种类型,想必前端改起来会非常麻烦,而且极其容易出错。 那么有没有好的方式解决如下场景与问题呢?

  • 问题1: js 或者 template 中 if判断的魔法数字问题
  • 问题2:需要获取 type 对应的 中文字面意义,如列表渲染
  • 场景3:下拉列表需要显示 整个常量的 label和value对应
  • 场景4:需要将 label和value 数组,转为一个对象

# 二、架构思想

对于上面的情况,分析问题,有两个核心字段: 1)label,字面意义 2)value,具体的值;
比如: 性别字段: 男:1,女:0,未知:2
加上借鉴其他编程语言的常量思想:“常量放到一起”,所以肯定要将 label和value 组合的放到一起;
回到js中,组合其实就是一个对象。于是乎有了如下结构:

{
  label: '男',
  value: 1
}
{
  label: '女',
  value: 0
}
1
2
3
4
5
6
7
8

接着,我们如何在前端去掉魔法数字呢,那么肯定要使用变量去替换魔法数字,于是又有了下面的代码:

MAN = {
  label: '男',
  value: 1
};
WOMAN = {
  label: '女',
  value: 0
}
1
2
3
4
5
6
7
8

现在结构定义清楚了,那么接下来提供一些方法满足以上问题就可以了,请继续往下看

# 三、具体使用

在 SmartAdmin 1.X 中我们使用我们实验室研发的 vue-enum (opens new window)来解决了,但是在SmartAdmin 2.X 中我们还没来的及升级 vue-enum,故将这个插件写到了项目中,具体见:src/plugins/smart-enums-plugins 文件

# 3.1、使用方式

使用有两个步骤:

    1. constants目录创建自己的常量文件,然后定义常量,文件必须以-const为结尾,如employee-const.jsuser-const.js
    1. constants/index.js 文件中引入刚才自定义的常量(很多人容易忘记这个步骤!!!)

# 1)为什么要以 -const.js 为文件结尾?

  • 很方便快速找到文件,比如在文件搜索中直接输入 employee const,有且找到唯一的一个对应文件
  • 当看到文件时,知道这是一个 常量(枚举) 文件
  • 避免和 状态管理 vuex或者路由router 中、异或常量中的 employee.js 这类重名

# 2)写法

可以查看 constants/system/login-device-const.js, 格式必须参照如下,属性必须为valuedesc

export const LOGIN_DEVICE_ENUM = {
  PC: {
    value: 1,
    desc: '电脑端',
  },
  ANDROID: {
    value: 2,
    desc: '安卓',
  },
  APPLE: {
    value: 3,
    desc: '苹果',
  },
  H5: {
    value: 4,
    desc: 'H5',
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在 index.js 中引入

import { LOGIN_DEVICE_ENUM } from './system/login-device-const';

export default {
  LOGIN_DEVICE_ENUM,
};
1
2
3
4
5

# 3.2、使用方法

vue-enum提供三个常规方法以供页面内组件使用

方法名 参数名 结果
getDescByValue enumName,value 根据枚举值获取描述,返回:desc
getValueDescList enumName 根据枚举名获取对应的描述键值对,返回数组 [{value:desc},{value:desc}...{value:desc}]
getValueDesc enumName 根据枚举名获取对应的value描述键值对,返回对象 {value:desc}

例1、在template模板中使用getDescByValue方法:

 <a-badge status="geekblue" />
  {{ $smartEnumPlugin.getDescByValue('CHANGE_LOG_TYPE_ENUM', item.type) }}:{{ item.version }} 版本
 </a>
1
2
3

例2、在 js 中使用getValueDescList方法:

 const internalInstance = getCurrentInstance(); // 有效  全局
 const smartEnumPlugin = internalInstance.appContext.config.globalProperties.$smartEnumPlugin;
 const valueList = smartEnumPlugin.getValueDescList('LOGIN_DEVICE_ENUM');
1
2
3

例3、在 js 中使用getValueDesc方法:

 const internalInstance = getCurrentInstance(); // 有效  全局
 const smartEnumPlugin = internalInstance.appContext.config.globalProperties.$smartEnumPlugin;
 const obj = smartEnumPlugin.getValueDesc('LOGIN_DEVICE_ENUM');

返回:
{
  1:'电脑端',
  2:'安卓',
  3:'苹果',
  4:'H5',
}

1
2
3
4
5
6
7
8
9
10
11
12

# 四、实现原理

说出来来原理,就是遍历遍历,再遍历,具体可以看代码 smart-enums-plugin.js (opens new window)


# 联系我们

1024创新实验室-主任:卓大 (opens new window),混迹于各个技术圈,研究过计算机,熟悉点 java,略懂点前端。
1024创新实验室(河南·洛阳) (opens new window) 致力于成为中原领先、国内一流的技术团队,以技术创新为驱动,合作各类项目。

加 主任 “卓大” 微信
拉你入群,一起学习
关注 “小镇程序员”
分享代码与生活、技术与赚钱
请 “1024创新实验室” 喝咖啡
支持我们的开源与分享

告白气球 (钢琴版)
JESSE T