前端枚举最佳实践——优雅永不过时

痛点

很久很久以前,我在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);

接下来分一些场景来举例一些使用方法:

  1. 作某个字段的值映射
{
    title: '性别',  
    dataIndex: 'gender',  
    render: (gender) => genderEnums.getDescriptionFromValue(gender),
}
  1. select组件中需要传入选项
<Select  
    name="gender"  
    label="性别"
    options={genderEnums.getOptions}
/>

其余方法就留给大家自己探索吧,我觉得这个封装已经可以涵盖大部分的场景了,你觉得呢?

原文链接:https://juejin.cn/post/7221820151397335077 作者:AliPaPa

(0)
上一篇 2023年4月15日 上午10:46
下一篇 2023年4月15日 上午10:56

相关推荐

发表回复

登录后才能评论