用dumi发布一个用于处理枚举值的npm包

2,160 阅读2分钟

背景

前端开发的时候总是会用到枚举值,对于枚举值我们的应用场景如下:

  • 页面下拉框的枚举类型以及枚举类型对应的数字量
  • 后台返回数字量,前端需要显示对应的文本描述


以前我们的做法是分开放在不同的地方的,其实我还是想将数据来源放在统一的地方进行管理,然后根据数据源进行一个变体,一个支持枚举变量,一个支持数字量对应返回的文本描述


js版本

函数加载通过数据源 + 枚举注入 =》 生成对应的对象,想用到的方法通过方法直接获取就好。

image.png

index.js 枚举入口文件

commonEnum文件夹下的index,主要是工具函数,在业务文件调用时,返回对应的枚举对象。

/* eslint-disable camelcase */
import _ from "lodash";
import sourceData from "./sourceData";

const highForatFunction = enumSourceData => {
  // 根据数据源处理返回枚举类型
  const enumValue = {};

  _.forEach(enumSourceData, item => {
    enumValue[item.key] = item.value;
  });

  // 枚举数据源,根据value值获取lable文本值
  const getLabelByValue = value => {
    const filterObject = _.filter(enumSourceData, item => item.value === value);

    // 存在返回值,返回第一个匹配的数据
    if (filterObject.length) {
      return filterObject[0].label;
    }

    // 没有返回值的情况下,返回空
    return "";
  };

  return {
    enum: enumValue,
    getLabelByValue
  };
};

const injectEnumFunction = sourceDataKeyArray => {
  // 数据类型检查
  if (!_.isArray(sourceDataKeyArray)) {
    throw new Error("注入失败,参数格式不正确");
  }

  const injectEnumOject = {};

  _.forEach(sourceDataKeyArray, item => {
    // eslint-disable-next-line no-prototype-builtins
    if (sourceData.hasOwnProperty(item)) {
      injectEnumOject[item] = highForatFunction(sourceData[item]);
    } else {
      throw new Error(`注入失败,没有${item}对应的枚举数据`);
    }
  });
  return injectEnumOject;
};

export default injectEnumFunction;


sourceData.js 数据源文件

数据源文件:枚举主题内部的每一个单体对象,内部的三个属性值:key,value,label。

const sourceData = {
  userAccountTypeEnum: [
    {
      key: "STAFF",
      value: 1,
      label: "员工"
    },
    {
      key: "COMPANY",
      value: 2,
      label: "公司"
    }
  ]
};

export default sourceData;


使用方式

image.png

引入injectEnumFunction

import injectEnumFunction from "@/common/commonEnum";

调用方式,注入userAccountTypeEnum枚举类型值

const { userAccountTypeEnum } = injectEnumFunction(["userAccountTypeEnum"]);

得到的结果是:
image.png
返回的结果是两个属性,一个是enum枚举值。另一个是一个function,用于通过key值获取对应的文本信息。


dumi & ts版本

github源代码

创建项目

dumi官网

yarn create @umijs/dumi-lib --site


代码结构

image.png

核心代码

// index.ts
import _ from 'lodash';
import {
  EnumItem,
  EnumBase,
  TypeEnum,
  InjectEnumObject,
  SourceData,
} from './type';

class EnumStoreClass {
  private _sourceData: SourceData = {};

  private _highForatFunction = (enumSourceData: EnumItem[]) => {
    // 根据数据源处理返回枚举类型
    const enumValue: EnumBase = {};

    _.forEach(enumSourceData, (item) => {
      enumValue[item.key] = item.value;
    });

    // 枚举数据源,根据value值获取lable文本值
    const getLabelByValue = (value: TypeEnum) => {
      const filterObject = _.filter(
        enumSourceData,
        (item) => item.value === value,
      );

      // 存在返回值,返回第一个匹配的数据
      if (filterObject.length) {
        return filterObject[0].label;
      }

      // 没有返回值的情况下,返回空
      return '';
    };

    return {
      enum: enumValue,
      getLabelByValue,
    };
  };

  public initData(initData: SourceData) {
    this._sourceData = initData;
  }

  public injectEnumFunction = (sourceDataKeyArray: string[]) => {
    // 数据类型检查
    if (!_.isArray(sourceDataKeyArray)) {
      throw new Error('注入失败,参数格式不正确');
    }

    const injectEnumOject: InjectEnumObject = {};

    _.forEach(sourceDataKeyArray, (item) => {
      // eslint-disable-next-line no-prototype-builtins
      if (this._sourceData.hasOwnProperty(item)) {
        injectEnumOject[item] = this._highForatFunction(this._sourceData[item]);
      } else {
        throw new Error(`注入失败,没有${item}对应的枚举数据`);
      }
    });
    return injectEnumOject;
  };
}

const enumStore = new EnumStoreClass();

export const initEnumSourceData = (initData: SourceData) => {
  enumStore.initData(initData);
};

export const injectEnumFunction = (sourceDataKeyArray: string[]) => {
  return enumStore.injectEnumFunction(sourceDataKeyArray);
};

export * from './type';
// type.ts
export type TypeEnum = number | string;

export interface EnumItem {
  key: TypeEnum;
  label: TypeEnum;
  value: TypeEnum;
}

export interface EnumBase {
  [key: number]: TypeEnum;
  [key: string]: TypeEnum;
}

export interface InjectEnumItem {
  enum?: EnumBase;
  getLabelByValue?: Function;
}

export interface InjectEnumObject {
  [key: string]: InjectEnumItem;
}

export interface SourceData {
  [key: string]: EnumItem[];
}


使用

import React from 'react';
import { injectEnumFunction, initEnumSourceData, SourceData } from 'rofo-enum';

const sourceData: SourceData = {
  userAccountTypeEnum: [
    {
      key: 'STAFF',
      value: 1,
      label: '员工',
    },
    {
      key: 'COMPANY',
      value: 2,
      label: '公司',
    },
  ],
};

for (let i = 0; i < 10000; i++) {
  sourceData['userAccountTypeEnum' + i] = [
    {
      key: 'STAFF',
      value: 1,
      label: '员工',
    },
    {
      key: 'COMPANY',
      value: 2,
      label: '公司',
    },
  ];
}

initEnumSourceData(sourceData);

console.time('test-start');
const { userAccountTypeEnum9999 } = injectEnumFunction([
  'userAccountTypeEnum9999',
]);

console.log(userAccountTypeEnum9999.enum);

console.log(userAccountTypeEnum9999.getLabelByValue(1));

console.timeEnd('test-start');

性能测试

这里用了console.time进行性能测试。因为是属性访问,所以性能没什么影响。

image.png



本地如何调试

当我们还没有将代码发布到npm当中的时候,可以本地如下设置:

image.png

然后示例中就可以直接像下面这种代码使用进行测试:

import { injectEnumFunction, initEnumSourceData, SourceData } from 'rofo-enum';



发布在线npm包

当我们写好代码,写好在线文档,提交代码,然后发布版本。

npm run release

image.png

然后到npm网站就可以看到发布的包【这里的readme没有修改好,不耽误使用】

www.npmjs.com/package/rof…
image.png


发布在线文档

npm run deploy

image.png

然后到对应的github项目地址当中可以看到gh-pages分支

image.png
image.png

点击查看:页面是空白,主要原因是这里的路径访问是有二级域名的,所以需要重新修改一下代码。

image.png


这里是为了适配github部署网站

image.png

然后我们就可以看到我们部署的网站

image.png