前端枚举库 enum-plus 引领技术潮流:UI 组件自动生成,大幅提升开发效率

06-01 1230阅读

Github

前端枚举库 enum-plus 引领技术潮流:UI 组件自动生成,大幅提升开发效率 像原生 enum 一样,但更强大!

 

⬇️    简介  |  特性  |  安装  |  枚举定义  |  API  |  用法  |  本地化  |  全局扩展  |  兼容性    ⬇️

简介

enum-plus是一个增强版的枚举类库,完全兼容原生enum的基本用法,同时支持扩展显示文本、绑定到 UI 组件以及提供丰富的扩展方法,是原生enum的一个直接替代品。它是一个轻量级、零依赖、100% TypeScript 实现的工具,适用于多种前端框架,并支持本地化。

枚举项列表可以用来一键生成下拉框、复选框等组件,可以轻松遍历枚举项数组,获取某个枚举值的显示文本,判断某个值是否存在等。支持本地化,可以根据当前语言环境返回对应的文本,轻松满足国际化的需求。

还有哪些令人兴奋的特性呢?请继续探索吧!或者不妨先看下这个使用视频。

前端枚举库 enum-plus 引领技术潮流:UI 组件自动生成,大幅提升开发效率

特性

  • 完全兼容原生 enum 的用法
  • 支持number、string等多种数据类型
  • 增强的枚举项,支持自定义显示文本
  • 内置本地化能力,枚举项文本可实现国际化,可与任何 i18n 库集成
  • 支持枚举值转换为显示文本,代码更简洁
  • 可扩展设计,允许在枚举项上添加自定义字段
  • 支持将枚举绑定到 Ant Design、ElementPlus、Material-UI 等 UI 库,一行代码枚举变下拉框
  • 支持 Node.js 环境,支持服务端渲染(SSR)
  • 零依赖,纯原生 JavaScript,可用于任何前端框架
  • 100% TypeScript 实现,具有全面的类型推断能力
  • 轻量(gzip 压缩后仅 2KB+)

    安装

    npm install enum-plus
    

    枚举定义

    本节展示了使用 Enum 函数初始化枚举的多种方式,你可以根据不同的使用场景选择最合适的方法

    1. 基础格式,与原生枚举用法基本一致

    import { Enum } from 'enum-plus';
    const Week = Enum({
      Sunday: 0,
      Monday: 1,
    } as const);
    Week.Monday; // 1
    

    as const 类型断言用于将枚举值变成字面量类型,类型更精确,否则它们将被作为number类型。如果你使用的是JavaScript,请删除as const

    2. 标准格式(推荐)

    为每个枚举项指定 value (枚举值) 和 label(显示文本)字段,这是最常用的格式,也是推荐的格式。这种格式允许你为每个枚举项设置显示文本,这些文本可以在UI组件中使用

    import { Enum } from 'enum-plus';
    const Week = Enum({
      Sunday: { value: 0, label: '星期日' },
      Monday: { value: 1, label: '星期一' },
    } as const);
    Week.Sunday; // 0
    Week.label(0); // 星期日
    

    3. 数组格式

    数组格式在需要动态创建枚举时很有用,例如从 API 获取数据中动态创建一个枚举。这种方式还允许自定义字段映射,这增加了灵活性,可以适配不同的数据格式

    import { Enum } from 'enum-plus';
    const petTypes = await getPetsData();
    // [   { value: 1, key: 'dog', label: '狗' },
    //     { value: 2, key: 'cat', label: '猫' },
    //     { value: 3, key: 'rabbit', label: '兔子' }   ];
    const PetTypes = Enum(petTypes);
    

    4. 原生枚举格式

    如果你已经有一个原生的枚举,你可以直接传递给Enum函数,它会自动转换为增强版的枚举,这样可以借用原生枚举的枚举值自动递增特性

    import { Enum } from 'enum-plus';
    enum init {
      Sunday = 0,
      Monday,
      Tuesday,
      Wednesday,
      Thursday,
      Friday,
      Saturday,
    }
    const Week = Enum(init);
    Week.Sunday; // 0
    Week.Monday; // 1
    Week.Saturday; // 6
    Week.label('Sunday'); // Sunday
    

    API

    💎    拾取枚举值

    Enum.XXX

    像原生enum一样,直接拾取一个枚举值

    Week.Sunday; // 0
    Week.Monday; // 1
    

    💎    items

    { value, label, key, raw }[]

    获取一个包含全部枚举项的只读数组,可以方便地遍历枚举项。由于符合 Ant Design 组件的数据规范,因此支持将枚举一键转换成下拉框、复选框等组件,只需要一行代码!


    💎    keys

    string[]

    获取一个包含全部枚举项Key的只读数组


    💎    label

    [方法]   label(keyOrValue?: string | number): string | undefined

    根据某个枚举值或枚举 Key,获取该枚举项的显示文本。如果设置了本地化,则会返回本地化后的文本。

    Week.label(1); // 星期一
    Week.label('Monday'); // 星期一
    

    💎    key

    [方法]   key(value?: string | number): string | undefined

    根据枚举值获取该枚举项的 Key,如果不存在则返回undefined

    Week.key(1); // 'Monday'
    

    💎    has

    [方法]   has(keyOrValue?: string | number): boolean

    判断某个枚举项(值或 Key)是否存在

    Week.has(1); // true
    Week.has('Sunday'); // true
    Week.has(9); // false
    Week.has('Birthday'); // false
    

    💎    toSelect

    [方法]   toSelect(config?: OptionsConfig): {value, label}[]

    toSelect与items相似,都是返回一个包含全部枚举项的数组。区别是,toSelect返回的元素只包含label和value两个字段,同时,toSelect方法支持在数组头部插入一个可自定义的默认元素,一般用于下拉框等组件的默认选项


    💎    toMenu

    [方法]   toMenu(): { key, label }[]

    生成一个对象数组,可以绑定给 Ant Design 的Menu、Dropdown等组件

    import { Menu } from 'antd';
    Week.toMenu()} /;
    

    数据数据格式为:

    [
      { key: 0, label: '星期日' },
      { key: 1, label: '星期一' },
    ];
    

    💎    toFilter

    [方法]   toFilter(): { text, value }[]

    生成一个对象数组,可以直接传递给 Ant Design Table 组件的列配置,在表头中显示一个下拉筛选框,用来过滤表格数据

    数据数据格式为:

    [
      { text: '星期日', value: 0 },
      { text: '星期一', value: 1 },
    ];
    

    💎    toValueMap

    [方法]   toValueMap(): Record

    生成一个符合 Ant Design Pro 规范的枚举集合对象,可以传递给 ProFormField、ProTable 等组件。

    数据格式为:

    {
      0: { text: '星期日' },
      1: { text: '星期一' },
    }
    

    💎    raw

    方法重载^1 raw(): Record

    方法重载^2 raw(keyOrValue: V | K): T[K]

    第一个重载方法,返回枚举集合的初始化对象,即用来初始化 Enum 原始 init 对象。

    第二个重载方法,用来处理单个枚举项,根据获取单个枚举项的原始初始化对象。

    这个方法主要作用是,用来获取枚举项的自定义字段,支持无限扩展字段

    const Week = Enum({
      Sunday: { value: 0, label: '星期日', happy: true },
      Monday: { value: 1, label: '星期一', happy: false },
    } as const);
    Week.raw(0).happy // true
    Week.raw(0); // { value: 0, label: '星期日', happy: true }
    Week.raw('Monday'); // { value: 1, label: '星期一', happy: false }
    Week.raw(); // { Sunday: { value: 0, label: '星期日', happy: true }, Monday: { value: 1, label: '星期一', happy: false } }
    

    ⚡️    valueType TypeScript ONLY

    value1 | value2 | ...

    在 TypeScript 中,提供了一个包含所有枚举值的联合类型,用于缩小变量或组件属性的数据类型。这种类型替代了像 number 或 string 这样宽泛的原始类型,使用精确的值集合,防止无效赋值,同时提高代码可读性和编译时类型安全性。

    type WeekValues = typeof Week.valueType; // 0 | 1
    const weekValue: typeof Week.valueType = 1; // ✅ 类型正确,1 是一个有效的周枚举值
    const weeks: (typeof Week.valueType)[] = [0, 1]; // ✅ 类型正确,0 和 1 是有效的周枚举值
    const badWeekValue: typeof Week.valueType = 8; // ❌ 类型错误,8 不是一个有效的周枚举值
    const badWeeks: (typeof Week.valueType)[] = [0, 8]; // ❌ 类型错误,8 不是一个有效的周枚举值
    

    注意,这只是一个 TypeScript 类型,只能用来约束类型,不可在运行时调用,运行时调用会抛出异常


    用法

    •   基本用法,与原生枚举用法一致

    const Week = Enum({
      Sunday: { value: 0, label: '星期日' },
      Monday: { value: 1, label: '星期一' },
    } as const);
    Week.Sunday; // 0
    Week.Monday; // 1
    

    •   支持为枚举项添加 Jsdoc 注释,代码提示更友好

    在代码编辑器中,将光标悬停在枚举项上,即可显示关于该枚举项的详细 Jsdoc 注释,而不必再转到枚举定义处查看

    const Week = Enum({
      /** 星期日 */
      Sunday: { value: 0, label: '星期日' },
      /** 星期一 */
      Monday: { value: 1, label: '星期一' },
    } as const);
    Week.Monday; // 将光标悬浮在 Monday 上
    

    前端枚举库 enum-plus 引领技术潮流:UI 组件自动生成,大幅提升开发效率

    可以看到,不但提示了枚举项的释义,还有枚举项的值,在阅读代码时非常方便


    •   获取包含全部枚举项的数组

    Week.items; // 输出如下:
    // [
    //  { value: 0, label: '星期日', key: 'Sunday', raw: { value: 0, label: '星期日' } },
    //  { value: 1, label: '星期一', key: 'Monday', raw: { value: 1, label: '星期一' } }
    // ]
    

    •   获取第一个枚举值

    Week.items[0].value; // 0
    

    •   检查一个值是否一个有效的枚举值

    Week.has(1); // true
    Week.items.some(item => item.value === 1); // true
    1 instanceof Week; // true
    

    •   支持遍历枚举项数组,但不可修改

    Week.items.length; // 2
    Week.items.map((item) => item.value); // [0, 1],✅ 可遍历
    Week.items.forEach((item) => {}); // ✅ 可遍历
    for (const item of Week.items) {
      // ✅ 可遍历
    }
    Week.items.push({ value: 2, label: '星期二' }); // ❌ 不可修改
    Week.items.splice(0, 1); // ❌ 不可修改
    Week.items[0].label = 'foo'; // ❌ 不可修改
    

    •   枚举值(或Key)转换为显示文本

    Week.label(1); // 星期一,
    Week.label(Week.Monday); // 星期一
    Week.label('Monday'); // 星期一
    

    •   枚举值转换为Key

    Week.key(1); // 'Monday'
    Week.key(Week.Monday); // 'Monday'
    Week.key(9); // undefined, 不存在此枚举项
    

    •   添加扩展字段,不限数量

    const Week = Enum({
      Sunday: { value: 0, label: '星期日', active: true, disabled: false },
      Monday: { value: 1, label: '星期一', active: false, disabled: true },
    } as const);
    Week.raw(0).active // true
    Week.raw(Week.Sunday).active // true
    Week.raw('Sunday').active // true
    

    🔥   转换成 UI 组件

    • 生成 Select 下拉框

      • Ant Design | Arco Design

        Select

        import { Select } from 'antd';
        ;
        
        • Material-UI Select
          import { MenuItem, Select } from '@mui/material';
          
            {Week.items.map((item) => (
              
                {item.label}
              
            ))}
          ;
          
          • Kendo UI Select
            import { DropDownList } from '@progress/kendo-react-dropdowns';
            ;
            
            • ElementPlus Select
                
              
              
              • Ant Design Vue | Arc Design Select
                 
                  
                • Vuetify Select
                   
                    
                  • Angular Material Select
                      {{ item.label }}
                    
                    
                    • NG-ZORRO Select
                        {{ item.label }}
                      
                      

                      • 生成下拉菜单

                        toMenu方法可以为 Ant Design Menu、Dropdown 等组件生成数据源,格式为:{ key: number|string, label: string } []

                        import { Menu } from 'antd';
                        Week.toMenu()} /;
                        
                        • 生成表格列筛选

                          toFilter方法可以生成一个对象数组,为表格绑定列筛选功能,列头中显示一个下拉筛选框,用来过滤表格数据。对象结构遵循 Ant Design 的数据规范,格式为:{ text: string, value: number|string } []

                          import { Table } from 'antd';
                          const columns = [
                            {
                              title: 'week',
                              dataIndex: 'week',
                              filters: Week.toFilter(),
                            },
                          ];
                          // 在表头中显示下拉筛选项
                          columns} /;
                          
                          • 支持 Ant Design Pro 组件生成

                            toValueMap方法可以为 Ant Design Pro 的ProFormFields、ProTable等组件生成数据源,这是一个类似 Map 的数据结构,格式为:{ [key: number|string]: { text: string } }

                            import { ProFormSelect, ProFormCheckbox, ProFormRadio, ProFormTreeSelect, ProTable } from '@ant-design/pro-components';
                            ; // 下拉框
                            ; // 复选框
                            ; // 单选框
                            ; // 树选择
                             dataIndex: 'week', valueEnum: Week.toValueMap() }]} /; // ProTable
                            

                            •   枚举合并(或者扩展枚举)

                            const myWeek = Enum({
                              ...Week.raw(),
                              Friday: { value: 5, label: '星期五' },
                              Saturday: { value: 6, label: '星期六' },
                            });
                            

                            •   使用枚举值序列来缩小 number 取值范围 [TypeScript ONLY]

                            使用 valueType 类型约束,可以将数据类型从宽泛的number或string类型缩小为有限的枚举值序列,这不但能减少错误赋值的可能性,还能提高代码的可读性

                            const weekValue: number = 8; // 👎 任意数字都可以赋值给周枚举,即使错误的
                            const weekName: string = 'Birthday'; // 👎 任意字符串都可以赋值给周枚举,即使错误的
                            const goodWeekValue: typeof Week.valueType = 1; // ✅ 类型正确,1 是一个有效的枚举值
                            const goodWeekName: typeof Week.keyType = 'Monday'; // ✅ 类型正确,'Monday' 是一个有效的枚举名
                            const badWeekValue: typeof Week.valueType = 8; // ❌ 类型报错,8 不是一个有效的枚举值
                            const badWeekName: typeof Week.keyType = 'Birthday'; // ❌ 类型报错,'Birthday' 不是一个有效的枚举值
                            type FooProps = {
                              value?: typeof Week.valueType; // 👍 组件属性类型约束,可以防止错误赋值,还能智能提示取值范围
                              names?: (typeof Week.keyType)[]; // 👍 组件属性类型约束,可以防止错误赋值,还能智能提示取值范围
                            };
                            

                            本地化

                            enum-plus 本身不内置国际化能力,但支持通过 localize 可选参数传入一个自定义方法,来实现本地化文本的转化。这是一个非常灵活的方案,这使你能够实现自定义的本地化函数,根据当前的语言环境将枚举的 label 值转换为适当的翻译文本。语言状态管理仍由您自己负责,您的 localize 方法决定返回哪种本地化文本。对于生产环境的应用程序,我们强烈建议使用成熟的国际化库(如 i18next),而不是创建自定义解决方案。

                            以下是一个简单的示例,仅供参考。请注意,第一种方法由于缺乏灵活性,不建议在生产环境中使用,它仅用于演示基本概念。请考虑使用第二种及后面的示例。

                            import { Enum } from 'enum-plus';
                            import i18next from 'i18next';
                            import Localize from './Localize';
                            let lang = 'zh-CN';
                            const setLang = (l: string) => {
                              lang = l;
                            };
                            // 👎 这不是一个好例子,仅供演示,不建议生产环境使用
                            const sillyLocalize = (content: string) => {
                              if (lang === 'zh-CN') {
                                switch (content) {
                                  case 'enum-plus.options.all':
                                    return '全部';
                                  case 'week.sunday':
                                    return '星期日';
                                  case 'week.monday':
                                    return '星期一';
                                  default:
                                    return content;
                                }
                              } else {
                                switch (content) {
                                  case 'enum-plus.options.all':
                                    return 'All';
                                  case 'week.sunday':
                                    return 'Sunday';
                                  case 'week.monday':
                                    return 'Monday';
                                  default:
                                    return content;
                                }
                              }
                            };
                            // 👍 建议使用 i18next 或其他国际化库
                            const i18nLocalize = (content: string | undefined) => i18next.t(content);
                            // 👍 或者封装成一个基础组件
                            const componentLocalize = (content: string | undefined) => content} /;
                            const Week = Enum(
                              {
                                Sunday: { value: 0, label: 'week.sunday' },
                                Monday: { value: 1, label: 'week.monday' },
                              } as const,
                              {
                                localize: sillyLocalize,
                                // localize: i18nLocalize, // 👍 推荐使用i18类库
                                // localize: componentLocalize, // 👍 推荐使用组件形式
                              }
                            );
                            setLang('zh-CN');
                            Week.label(1); // 星期一
                            setLang('en-US');
                            Week.label(1); // Monday
                            

                            当然,每个枚举类型都这样设置可能比较繁琐,enum-plus 提供了一种全局设置方案,可以通过 Enum.localize 全局方法,来全局设置本地化。如果两者同时存在,单个枚举的设置会覆盖全局设置。

                            Enum.localize = i18nLocalize;
                            

                            全局扩展

                            虽然 Enum 提供了一套全面的内置方法,但如果这些还不能满足你的需求,你可以使用 Enum.extends API 扩展其功能,添加自定义方法。这些扩展会全局应用于所有枚举实例,包括在扩展应用之前创建的实例,并且会立即生效,无需任何其它设置。

                            Enum.extends({
                              toMySelect(this: ReturnType) {
                                return this.items.map((item) => ({ value: item.value, title: item.label }));
                              },
                              reversedItems(this: ReturnType) {
                                return this.items.reverse();
                              },
                            });
                            Week.toMySelect(); // [{ value: 0, title: '星期日' }, { value: 1, title: '星期一' }]
                            

                            兼容性

                            enum-plus 提供了完善的兼容性支持。

                            • 浏览器环境:

                              • 现代打包工具:对于支持 exports 字段的打包工具(如 Webpack 5+、Vite、Rollup),enum-plus 的目标是 ES2020。如果需要更广泛的浏览器支持,可以在构建过程中使用 @babel/preset-env 转译为更早期的语法。

                              • 旧版打包工具:对于不支持 exports 字段的工具(如 Webpack 4),enum-plus 会自动回退到 main 字段的入口点,其目标是 ES2016。

                              • Polyfill 策略:为了最小化包的体积,enum-plus 不包含任何 polyfill。如果需要支持旧版浏览器,可以引入以下内容:

                                • core-js
                                • 配置适当的 @babel/preset-env 和 useBuiltIns 设置
                                • 其他替代的 polyfill 实现
                                • Node.js 兼容性:enum-plus 需要至少 ES2016 的特性,兼容 Node.js v7.x 及以上版本。


                                  意犹未尽,还期待更多?不妨移步 Github,你可以发现更多的高级使用技巧。

                                  相信我,一定会让你感觉相见恨晚!

                                  如果你喜欢这个项目,欢迎在 Github 上给项目点个 Star ⭐ —— 这是程序员表达喜爱的通用语言哈😜 ~ 可以让更多开发者发现它!

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码