前端枚举最佳规范——优雅可能也会过时
痛点
很久很久以前,我在ts项目中使用枚举是这样的
export enum GENDER {
MALE = 1,
FEMALE = 2,
}
export const GENDER_MAP: Record<GENDER, string> = {
[GENDER.MALE]: '男',
[GENDER.FEMALE]: '女',
}
// 可能还会写一个给select组件使用的options
export const GENDER_OPTIONS = [
{
label: '男',
value: GENDER.MALE
},
{
label: '女',
value: GENDER.FEMALE,
}
];
封装
淦!好麻烦。封装一下,暂时只封装了一个js版本的,想做成ts版本的请自行更改
import { invert, isArray } from 'lodash';
class Enum {
constructor(enumsName) {
this.enumsName = enumsName;
this.enums = {};
}
// 设置枚举项
setItem(desc, value) {
this.enums[desc] = value;
return this;
}
findEnumItem(value) {
return Object.keys(this.enums).find(
(desc) => this.getValueFromDesc(desc) === value,
);
}
// 根据值获取描述
getValueFromDesc(desc) {
return this.enums[desc];
}
getDescriptionFromValue(value, separator = ',') {
if (isArray(value)) {
return value.map((item) => this.findEnumItem(item)).join(separator);
} else {
return this.findEnumItem(value);
}
}
// 获取枚举第一项的值
getFirstValue() {
const enums = this.getEnums();
return enums[Object.keys(enums)[0]];
}
// 自定义转换枚举数组格式
transformEnums(formatTarget) {
// formatTarget 数组第一项是描述属性名称,第二项是枚举值属性名称
if (isArray(formatTarget) && formatTarget.length === 2) {
const [keyName, valueName] = formatTarget;
return Object.entries(this.enums).map((item) => {
const [desc, value] = item;
return {
[keyName]: desc,
[valueName]: value,
};
});
} else {
return [];
}
}
// 获取 options
getOptions() {
return Object.entries(this.enums).map((item) => {
const [desc, value] = item;
return {
label: desc,
value,
};
});
}
// 获取描述和值反转对象,输出 {value: desc}
getInvertEnums() {
return invert(this.enums);
}
is(enumsName) {
return this.enumsName === enumsName;
}
}
export default Enum;
export const getEnums = (enumsName, enums) =>
enums.find((enumItem) => enumItem.is(enumsName));
使用
ok,咋使用呢?首先当然要创建枚举啦
// commonEnum.js
import Enum from '@/utils/enum';
// 我习惯把同一个模块或功能中的枚举全都塞到一个数组中
export const COMMON_ENUMS = [
new Enum('性别').setItem('男', 1).setItem('女', 2),
...
];
在使用到的地方,先获取你想要的枚举
import {getEnums} from '@/utils/enum';
import {COMMON_ENUMS} from '@/enum/commonEnum';
const genderEnums = getEnums('性别', COMMON_ENUMS);
接下来分一些场景来举例一些使用方法:
作某个字段的值映射
{
title: '性别',
dataIndex: 'gender',
render: (gender) => genderEnums.getDescriptionFromValue(gender),
}
select组件中需要传入选项
<Select
name="gender"
label="性别"
options={genderEnums.getOptions}
/>
其余方法就留给大家自己探索吧,我觉得这个封装已经可以涵盖大部分的场景了,你觉得呢?
作者:AliPaPa
来源:juejin.cn/post/7221820151397335077