通过学习mayfly,我学会了前端如何优雅设计字典值

简介: `shigen`是一位擅长多种编程语言的博主,他在探索[mayfly-go](https://juejin.cn/post/7319365035552309248)项目后,发现了对枚举值管理的优雅设计。他分享了如何将字典和枚举值结构化,使用Vue+typescript实现更易维护的代码。通过创建`TagType`和`EnumValue`类,以及提供静态方法,实现了模块化和简洁的字典处理。示例展示了如何在页面中高效引用和显示字典数据,提高了代码的可读性和可维护性。

shigen坚持更新文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。
个人IP:shigen

shigen在假期的最后一天早晨起来,翻看了一下博客,一个mayfly-go的开源项目吸引了我的注意力,其实很久之前准备去啃它的,后来看到了代码就放弃了。现在正好有这个决心,打开了mayfly-go官网准备学习一番。发现官方给的更多的是展示的效果,没有详细的设计文档和技术文档,直到我我找到了mayfly-go的语雀文档,认真的研读了一番,最后在枚举值统一管理维护这一块看得我豁然开朗。因为在shigen之前的文章后段数据字典的优雅设计的文墨就提到了我的困惑,也接触了很多稀烂的项目,所以困惑更深,设篇文章的设计正好为我提供了一个巧妙的解决方案。于是,我花了一下午的时间来研究者问题,并写了如下的代码验证。

技术选型:Vue+typescript

字典,我相信对于开发者来说并不陌生。我就直接展开讲述。

设计反例

直接揉在代码里,最后代码就是一坨shi。

<template>
  <div>
    <el-select v-model="type" placeholder="please select type">
      <el-option :key="1" label="菜单" :value="1"></el-option>
      <el-option :key="2" label="资源" :value="2"></el-option>
    </el-select>
    <p>type: {
   
   {
   
    getTypeTag(type) }}</p>
  </div>
</template>

<script>
export default {
   
   
  data() {
   
   
    return {
   
   
      type: 1,
    }
  },
  methods: {
   
   
    getTypeTag(type) {
   
   
      switch (type) {
   
   
        case 1: return "菜单";
        case 2: return "资源";
      }
    },
  }
}
</script>

无可否认,效果达到了。

实现效果

但是,细细想一下,代码的维护起来,维护的成本不言而喻。

我就直接展示我借助【mayfly-go】获得的思路。

优雅设计

首先,我们提取枚举值,或者说字典值的共性:

export class TagType {
   
   
  type: string;
}

结合element-ui el-rag文档,我们标签或者按钮的类型只有几个固定的选项,primarysuccess,warring等等。所以,我们的标签类型只需要一个type字段,且约束为字符串类型。

对于字典值,我们抽象如下:

export interface EnumValue {
   
   
  value: any;
  label: string;
  type: TagType;
}

一个标签,一个字典值,一个字典类型(可有可无)。抽象一下,就很好办了,我们有了对于字典定义和构造的能力了。

export class TagType {
   
   
  type: string;

  constructor(type: string) {
   
   
    this.type = type;
  }

  public static of(type = 'primary'): TagType {
   
   
    return new TagType(type);
  }

  public static tagTypeInfo(): TagType {
   
   
    return TagType.of('info');
  }

  public static tagTypeSuccess(): TagType {
   
   
    return TagType.of('success');
  }

  public static tagTypeDanger(): TagType {
   
   
    return TagType.of('danger');
  }

  public static tagTypeWarning(): TagType {
   
   
    return TagType.of('warning');
  }
}

export interface EnumValue {
   
   
  value: any;
  label: string;
  type: TagType;
}

export class EnumValue {
   
   
  value: any;
  label: string;
  type: TagType;

  constructor(value: any, label: string, type = TagType.of('primary')) {
   
   
    this.value = value;
    this.label = label;
    this.type = type;
  }

  public static of(value: any, label: string, type = TagType.of('primary')): EnumValue {
   
   
    return new EnumValue(value, label, type);
  }
}

第一次尝试写ts的模块化开发,还有点不习惯,毕竟脑子里还是Java。

OK,现在我们还需要在一堆同类型的字典中获得特定的字典,或者特定的字典属性。继续:

  public static getEnumByValue(enumValues: EnumValue[], value: any): EnumValue | null {
   
   
    const enums = Object.values(enumValues);
    return enums.find(enumValue => enumValue.value === value) || null;
  }

  public static getLabelByValue<T extends EnumValue>(enumValues: T[], value: any): string {
   
   
    const enums = Object.values(enumValues);
    const enumValue = enums.find(enumItem => enumItem.value === value);
    return enumValue ? enumValue.label : '';
  }

这里,ES6的新语法安排上。

现在就是我们业务字段枚举的组装问题,快看看我的设计:

import {
   
    EnumValue, TagType } from "@/common/Enum";

export const ResourceTypeEnum = {
   
   
  Menu: EnumValue.of(1, "菜单"),
  Resource: EnumValue.of(2, "资源"),
}

export const ResourceStatusTypeEnum = {
   
   
  Enable: EnumValue.of(true, "Enable", TagType.tagTypeSuccess()),
  Disable: EnumValue.of(false, "Disable", TagType.tagTypeDanger()),
}

称不上优雅,但至少看起来简洁明了,容易理解。

在具体的页面上,我们只需要引入对应的资源即可。

<template>
  <div>
    <h2>资源类型</h2>
    <el-select v-model="resourceType" placeholder="please select resouce type">
      <el-option v-for="(resourceType, index) in ResourceTypeEnum" :key="index" :label="resourceType.label"
        :value="resourceType.value"></el-option>
    </el-select>
    <p>label:{
   
   {
   
    getLabelByValue(ResourceTypeEnum, resourceType) }}</p>

    <h2>资源类型状态</h2>
    <el-tag v-for="(status, index) in ResourceStatusTypeEnum" :key="index" :type="status.type.type"
      :value="resourceType.value"> {
   
   {
   
    status.label }}
    </el-tag>
  </div>
</template>

<script>
import EnumValue from '@/common/Enum';
import {
   
    ResourceTypeEnum, ResourceStatusTypeEnum } from '@/views/system/enum';
export default {
   
   
  data() {
   
   
    return {
   
   
      resourceType: 1,
      resourceTypeStatus: false,
      // 需要引入,避免报错undefined
      ResourceTypeEnum,
      ResourceStatusTypeEnum,
    }
  },
  methods: {
   
   
    getLabelByValue(enums, value) {
   
   
      return EnumValue.getLabelByValue(enums, value);
    }
  }
}
</script>

现在页面效果是这样的:

页面效果

最大的优势就在于我在自己的页面代码看不到任何的字典设计和定义,完全是从一个文件中引入的。修改的话,只需要在enum.ts中修改即可。

当然,我印象中看到了有一种设计是把所有的字典值放在一个文件,如yaml文件中维护的。其实都是简化的方式,比传统的硬编码舒服多了。

与shigen一起,每天不一样!

目录
相关文章
|
8月前
|
前端开发 JavaScript 算法
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
transition过渡属性 早期在Web中要实现动画效果,都是依赖于JavaScript或Flash来完成。 但在CSS3中新增加了一个新的模块transition,它可以通过一些简单的CSS事件来触发元素的外观变化, 让效果显得更加细腻。简单点说,就是通过鼠标经过、获得焦点,被点击或对元素任何改变中触发, 并平滑地以动画效果改变CSS的属性值。 在CSS中创建简单的过渡效果可以从以下几个步骤来实现: 在默认样式中声明元素的初始状态样式; 声明过渡元素最终状态样式,比如悬浮状态; 在默认样式中通过添加
397 1
|
8月前
|
前端开发 JavaScript 算法
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
transform变形 css3在原来的基础上新增了变形和动画相关属性,通过这些属性可以实现以前需要大段JavaScript才能实现的 功能。 CSS3的变形功能可以对HTML组件执行位移、旋转、缩放、倾斜4种几何变换,这样的变换可以控制HTML组件 呈现出丰富的外观。 借助于位移、旋转、缩放、倾斜这4种几何变换,CSS3提供了transition动画。 transition动画比较简单,只要指定HTML组件的哪些CSS属性需要使用动画效果来执行变化,并指定动画时间,就可保证动画播放。 比transitio
387 1
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
1008 0
|
Dart 前端开发 架构师
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
698 26
|
前端开发 开发者 C++
独家揭秘:前端大牛们如何高效学习新技术,保持竞争力!
【10月更文挑战第31天】前端技术飞速发展,如何高效学习新技术成为关键。本文通过对比普通开发者与大牛们的策略,揭示了高效学习的秘诀:明确目标、主动探索、系统资源、实践应用和持续学习。通过这些方法,大牛们能更好地掌握新技术,保持竞争力。示例代码展示了如何通过实践加深理解。
354 4
|
前端开发 Java 编译器
【前端学java】如何从前端视角快速学习Maven
【8月更文挑战第12天】如何从前端视角快速学习Maven
353 2
【前端学java】如何从前端视角快速学习Maven
|
JavaScript 前端开发 Java
VUE学习四:前端模块化,ES6和ES5如何实现模块化
这篇文章介绍了前端模块化的概念,以及如何在ES6和ES5中实现模块化,包括ES6模块化的基本用法、默认导出与混合导出、重命名export和import,以及ES6之前如何通过函数闭包和CommonJS规范实现模块化。
633 0
VUE学习四:前端模块化,ES6和ES5如何实现模块化
|
前端开发 JavaScript 小程序
前端新机遇!为什么我建议学习鸿蒙?
【10月更文挑战第4天】前端新机遇!为什么我建议学习鸿蒙?
743 0
前端新机遇!为什么我建议学习鸿蒙?
|
前端开发 算法 网络协议
如何学习计算机基础知识,打好前端和网络安全的基础
如何学习计算机基础知识,打好前端和网络安全的基础
476 4
|
前端开发 JavaScript
前端网站学习大全
这篇文章提供了前端网站开发学习的资源大全,涵盖了HTML常用标签和CSS常用样式,以及如何使用`<meta>`标签提供页面元信息和`lang`属性定义内容语言等基础知识。
前端网站学习大全

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1162
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    511
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    397
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    387
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    504
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    676
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1190
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    267
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    990
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    458