Javascript 枚举工具封装

项目中少不了要管理一些相对固定的状态、类型,并耦合进业务判断中,为了统一管理,下面是一个枚举工具的封装。

先来看看使用:

// 控件中绑定
  <div>
    <!-- 以 ant-design-vue 为例 -->
    <!-- 绑定下拉列表数据 -->
    <a-select :options="EStatus._list"></a-select>

    <!-- 按不同样式展示中文 -->
    <div :class="EStatus._classOf(detail.status)">
        {{ EStatus._of(detail.status) }}
    </div>

    <!-- 判断 -->
    <div v-if="detail.status === EStatus.eNormal">
        ...
    </div>
  </div>

// js中使用
import { EStatus } from '@/enum/index.js'

// 这是后端返回的详情对象,比如状态status,后端一般只返回编码,展示时需要转成中文
const detail = {
  id: 1,
  name: 'xxx',
  status: 1
}

// 前端展示时转成中文
EStatus._of(detail.status) // 结果为:'正常'

// 判断状态是否为正常
if (detail.status === EStatus.eNormal) {
  // xxx
}

// 获取所有枚举对象,用于绑定到下拉列表等组件上
const list = EStatus._list // [{id, name, ... }, {id, name, ...}]

// 获取枚举对象
const enumObj = EStatus._objectOf(detail.status) // {id, name, ...}

// 其他自定义方法
const canEdit = EStatus._canEdit(detail.status)

枚举定义 @/enum/index.js 代码如下: 

import { Enum, init } from '@/utils/enum.util.js'
/**
 * 状态
 */
export const EStatus = {
  eNormal: Enum(1, '正常', 'text-success'), // 第三个参数为字符串时代表class样式,为boolean时代表disabled是否禁用,为object时代表data自定义扩展对象
  eError: Enum(2, '异常', 'text-warning'),

  // 其他自定义方法,统一使用”_“开头(方便代码提示,个人习惯,非强制)
  _canEdit (id) {
    return [this.eNormal].includes(id)
  }
}
init(EStatus) // 为 EStatus 统一添加通用属性和方法

/**
 * 其他枚举
 */
// export const EXxxx = {...}
// init(EXxxx)

上述引用的工具类 @/utils/enum.util.js 代码如下:

/**
 * 枚举对象
 * extra 为 boolean 时代表 disabled
 * extra 为 string 时代表 class
 * extra 为 object 时代表 data,此时第四个参数 data 无效
 * data 代表扩展属性
 * {id, name, disabled} or {id, name, class} or {id, name, data} or {id, name, disabled, data} or {id, name, class, data}
 */
export const Enum = (id, name, extra, data = {}) => {
  const disabled = typeof extra === 'boolean' ? extra : (data.disabled || false)
  const _class = typeof extra === 'string' ? extra : data.class
  const _data = typeof extra === 'object' ? extra : data
  return {
    id,
    name,
    disabled,
    class: _class,
    data: _data,
    key: id,
    value: id,
    label: name,
    title: name,
    text: name,
    isEnum: true,
    toString () {
      return this.id
    }
  }
}

/**
 * 初始化
 */
export function init (enumObj) {
  const keys = Object.keys(enumObj).filter((key) => enumObj[key].isEnum)
  enumObj._list = keys.map((key) => ({ ...enumObj[key] }))
  // 为了简化大部分使用情况,用ID覆盖原本的对象,要获取对象请用 _objectOf 方法
  for (let i in keys) {
    enumObj[keys[i]] = enumObj[keys[i]].id
  }
  enumObj._of = (id, default = '-') => {
    return enumObj._objectOf(id).name ?? default
  }
  enumObj._objectOf = (id, useDefault = true) => {
    let result = enumObj._list.find((item) => item.id === id || String(item.id) === String(id))
    return useDefault ? (result || Enum()) : result
  }
  enumObj._classOf = (id) => {
    return enumObj._objectOf(id).class
  }
  Object.freeze?.(enumObj)
}

如果对您有用,请点赞收藏哦~

可以关注我的低代码开源框架,可以用于后台管理项目快速开发,地址:base-backend-static: Vue3 + Vite + pinia + Ant design4 + js + axios + vue router + pnpmhttps://gitee.com/czleing/base-backend-static

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐