vue3项目中的字典功能

文章介绍了在前端使用TS重写和优化若依平台的字典功能,包括数据结构设计、自定义字典数据加载和el-tag插件的升级。优化点涉及避免不推荐的mixin方法,增加对布尔型和枚举类型的支持,以及数据持久化处理。示例代码展示了DictDataClass、DictLoad和index.ts等关键组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

声明:
本方法参考“若依”平台的字典功能,部分数据结构以及后台请求方法参考该平台源代码。

问题引入

若依平台的字典模块使用简洁便利,但是仍存在一些有待改进的地方:

  • 该模块使用minxin方法在vue3中已不再被提倡;
  • 模块阅读难度较大。主要是个人水平所限;
  • 无法在el-table-column的filters中使用;
  • 无常用自定义常量的功能,如布尔型变量的展示;
  • 不能处理后台枚举类型数据;
  • 未实现数据持久化处理,需要不断请求后台数据;

实现

采用ts语言编写。

数据结构

文件名:DictDataClass.ts

其中class DictData可根据自己情况添加属性

/**
 * 字典数据、字典元数据结构定义
 *@author MuYi
 *@date 2023-3-15 21:14:12
 *@version 1.0
 **/
/**
 * 后台返回数据结构,即标签和值,可能使用的字段名
 */
export const DictDataDefaultField = {
    /**
     * 默认标签字段
     */
    LABEL: ['label', 'name', 'title'],
    /**
     * 默认值字段
     */
    VALUE: ['value', 'id', 'uid', 'key'],

}
/**
 * 字典集合数据结构
 * @constructor
 */
export const DictClassData = () => {
    return {
        owner: null,
        label: {},
        type: {}
    }
}

/**
 *   字典集合类
 * @property {Object} label 字典 {字典类型名:{值:标签...}...}对象集合
 * @property {Object} dict 字典对象 {字典类型名:{}:DictData ...}字典集合
 * @property {Array.<DictMeta>} _dictMetas 字典元数据数组
 */
export class Dict {
    private owner: null;
    public label: {};
    public type: {};

    /**
     *
     * @param typeName 指定有效时(非null或‘’),type、label数组同时初始化一个该类型名的属性
     */
    constructor(typeName?: string) {
        this.owner = null;
        this.label = {};
        this.type = {};
        if (typeName && typeName.trim() != '') {
            let name = typeName.trim();
            if (name != '') {
                this.label[name] = {};
                this.type[name] = [];
            }
        }
    }
}


/**
 * 字典数据单项结构定义
 * @property label{string} 标签
 * @property text{string} 标签,与label相同。以便直接把值付给el-table-column的filters
 * @property value {*} 值
 * @property raw 原始数据(后台java的DictData类)
 **/
export class DictData {
    label: string;
    text: string;
    value: string | number;
    raw: object;

    /**
     *
     * @param label 标签值
     * @param value 字典值
     * @param raw 原始数据
     */
    constructor(label: string, value: string | number, raw: object) {
        this.label = label
        this.text = this.label
        this.value = value
        this.raw = raw
    }
}


/**
 * 字典元数据
 * @property {String} type 类型
 * @property {Function} request 请求
 * @property {Function} responseConverter 后台数据映射方法
 * @property {String} label 标签字段
 * @property {String} value 值字段
 */
export class DictMeta {
    type: string;
    labelField: string;
    valueField: string;
    public request: object;

    /**
     *
     * @param typeName 类型
     * @param labelField 标签字段
     * @param valueField 值字段
     */
    constructor(typeName: string, labelField: string, valueField: string) {
        this.type = typeName;
        this.labelField = labelField
        this.valueField = valueField
    }
}

前端自定义字典数据

文件名:DefinedDictData.json

其中:cssClass、isDefault、listClass、sort属性用于el-tag展示的样式

{
  "#说明":" 组key必须为小写,且前缀必须为'_',",
  "_boolean": [
    {
      "label": "是",
      "value": "true",
      "cssClass": "",
      "dictType": "_boolean",
      "dictValue": true,
      "isDefault": "Y",
      "listClass": "primary",
      "sort": 1
    },
    {
      "label": "否",
      "value": "false",
      "cssClass": "",
      "dictType": "_boolean",
      "dictValue": false,
      "isDefault": "N",
      "listClass": "warring",
      "sort": 2
    }
  ]
}

数据加载

文件名:DictLoad.ts

字典挂接方法

文件名:index.ts
抱歉。没CSDN积分了,整点积分用。下载地址:全部代码

/**
 * 字典数据
 * <pre>
 * </pre>
 *@author MuYi
 *@date 2023/3/15 21:38
 *@version 1.0
 **/
import {DictData, DictMeta, Dict} from "~/composables/dict/DictDataClass";
import {getDictEnumList} from '~/api/system/dict/data'
import {requestDict} from "~/composables/dict/DictLoad";

const DEFAULT_DICT_META = {
    type: '',
    labelField: 'label',
    valueField: 'dictValue',
    request(dictType: string) {
        return getDictEnumList(dictType).then(res => (res && res.data) ? (res.data) : [{}])
    }
}
/**
 * 加载字典数据
 * <pre>
 *     dictsTypeName约定:
 *     1 枚举enum类型以Enum开头
 *     2 自定义类型以"_"开头,如"_boolean"
 *     3 其他为系统提供dictType
 * </pre>
 * @param dictsTypeName 字典名称集合。字符串数组,或以逗号分隔的字符串
 * @param config
 * @constructor
 */
export const LoadDict = (dictsTypeName: string[] | string, config = DEFAULT_DICT_META): Dict => {
    let result = new Dict(null);
    let typeNames: string[] = getDictTypeNameArray(dictsTypeName);
    if (typeNames.length < 1) return result;
    for (let typeName of typeNames) {
        config.type = typeName;
        result.type[typeName] = [];
        result.label[typeName] = [];
        let dicts = requestDict(config, result)
    }

    return result;
}

const getDictTypeNameArray = (dicts: string[] | string): string[] => {
    if (!dicts) return [];
    let result: string[];
    if (dicts instanceof Array) {
        result = dicts;
    } else {
        result = dicts.toString().split(",")
    }
    for (let i = 0; i < result.length; i++) {
        result[i] = result[i].trim();
    }
    return result
}

el-tag插件升级

注:此代码为“若依”平台源代码

使用

<script setup="SysUser" lang="ts">
//from为上述代码的存放路径
import {LoadDict} from "~/composables/dict";
 //加载数据,依次为标准后台字典类型、后台enum类、自定义类型
const dict = LoadDict(['sys.yesNo', 'EnumExFormatType','_boolean']);
    <el-form-item label="下载类型" prop="exportType">
        <el-select>
          <el-option v-for="item in dict.type[EnumExFormatType]"
                        :key="item.value" :label="item.label" :value="item.value"/>
           </el-select>
   </el-form-item> 
   <el-table-column prop="cType" label="系统级别" resizable sortable
                      :filters="dict.type['sys.yesNo']" :filter-method="handleFilterChange">
       <template #default="scope">
           <dict-tag :options="dict.type['sys.yesNo']" :value="scope.row.cType"/>
       </template>
   </el-table-column>
<think>好的,我现在需要回答用户关于若依(Ruoyi)Vue前端项目字典功能是如何实现的问题。首先,我需要回忆一下若依框架的基本结构,尤其是前端部分如何处理字典功能。 用户之前的问题是关于Vue子组件获取父组件定义的ref名称,现在转向了另一个具体项目中的字典功能实现。这说明用户可能正在使用若依框架进行开发,遇到了字典相关的需求,或者想了解其实现机制。 首先,我需要明确字典功能在后台管理系统中的常见用途。通常,字典用于管理一些固定的键值对,比如状态、类型等,前端需要将这些键转换为对应的显示值。例如,数据库中存储的状态可能是0或1,前端需要显示为“启用”或“禁用”。 接下来,我需要回忆若依框架的前端部分是如何处理字典的。根据之前的了解,若依使用的是Vue前端,结合Element UI,并且会有一些封装好的组件和方法来处理字典数据。常见的做法包括全局注入字典数据、使用自定义指令或者组件来转换键值。 然后,我需要考虑具体的实现步骤。可能包括以下几个部分: 1. 字典数据的获取:前端如何从后端API获取字典数据。可能是在应用初始化时加载,或者在需要时按需加载。 2. 字典数据的存储:获取后的字典数据如何存储在Vue应用中,比如Vuex store或者全局变量。 3. 字典的使用:在组件中如何使用这些字典数据,比如通过过滤器、计算属性,或者自定义组件如下拉选择框。 可能涉及的代码部分包括: - 在全局的main.js中注册字典相关的工具方法或指令。 - 在Vuex中维护字典的状态,包括加载和获取字典的方法。 - 封装一个字典组件,比如<dict-tag>,用于显示字典标签,根据value显示对应的label。 - 使用混入(mixins)来复用字典相关的逻辑。 需要注意的是,若依框架可能有自己的实现方式,可能与其他常见做法有所不同。例如,使用@/utils/dict工具类来处理字典的获取和转换,或者在组件中通过特定的prop传递字典类型,然后组件内部处理显示。 另外,用户的问题可能关注的是如何在前端具体实现字典的展示,比如表格中显示状态对应的文字,表单中使用字典下拉框等。因此,需要详细说明这些场景下的实现方法,包括代码示例。 最后,我需要验证这些思路是否正确。可以回忆若依的官方文档或者查看其源码结构,确保回答的准确性。例如,在Ruoyi-Vue项目中,确实有一个dicts.js的工具文件,处理字典的获取和缓存,同时在组件中使用v-dict指令或者<dict-tag>组件来展示字典值。 总结起来,回答应该包括字典数据的加载、存储、使用的具体方法,并结合若依框架的代码结构进行说明,给出示例代码和步骤,确保用户能够理解并应用到实际开发中。</think>在 Ruoyi-Vue前端项目中,**字典功能(`dicts`)** 主要用于将后端返回的枚举值(如 `0/1`、`enable/disable`)转换为用户友好的文本展示(如 `启用/停用`)。以下是其核心实现逻辑: --- ### 一、字典功能的实现原理 Ruoyi 的字典功能通过 **全局混入(Mixin)** + **自定义指令/组件** 实现,核心步骤: 1. **字典数据加载** 在页面加载时,前端通过接口(如 `/system/dict/data/list`)从后端获取字典数据,缓存到 Vuex 或全局变量中。 **关键代码**(通常位于 `src/api/system/dict.js`): ```javascript export function getDicts(dictType) { return request({ url: &#39;/system/dict/data/list&#39;, method: &#39;get&#39;, params: { dictType } }) } ``` 2. **字典数据存储** 使用 Vuex 或全局对象缓存字典数据,避免重复请求: ```javascript // 示例:在 Vuex 中存储 const state = { dictData: {} // 格式:{ &#39;sys_user_sex&#39;: [{dictLabel: &#39;男&#39;, dictValue: &#39;0&#39;}, ...] } } ``` 3. **字典数据绑定** 在组件中通过 **`dicts` 属性** 声明需要使用的字典类型,自动触发加载和绑定: ```javascript export default { dicts: [&#39;sys_user_sex&#39;, &#39;sys_status&#39;], // 声明依赖的字典类型 data() { return { sex: &#39;&#39; } } } ``` --- ### 二、字典功能的具体使用方式 #### 1. 在表格中显示字典标签 使用 **`v-dict` 自定义指令** 或 **`<dict-tag>` 组件** 自动转换值: ```html <!-- 方式一:v-dict 指令 --> <el-table-column label="性别"> <template slot-scope="scope"> <span v-dict:sys_user_sex="scope.row.sex"></span> </template> </el-table-column> <!-- 方式二:<dict-tag> 组件 --> <dict-tag :value="scope.row.status" :type="&#39;sys_status&#39;" /> ``` #### 2. 在表单中使用字典下拉框 通过 **`<el-select>` + `dict` 属性** 绑定字典选项: ```html <el-form-item label="性别"> <el-select v-model="form.sex" placeholder="请选择"> <el-option v-for="item in dict.sys_user_sex" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" /> </el-select> </el-form-item> ``` #### 3. 手动获取字典数据 通过 **`this.getDicts` 方法** 动态获取字典(需在组件中声明 `dicts`): ```javascript export default { dicts: [&#39;sys_status&#39;], // 声明依赖的字典 methods: { loadData() { this.getDicts(&#39;sys_status&#39;).then(response => { this.statusOptions = response.data }) } } } ``` --- ### 三、核心代码解析 1. **全局混入(Mixin)** 在 `src/mixin/dict.js` 中,通过混入 `dicts` 声明逻辑,自动初始化字典: ```javascript export default { created() { if (this.dicts && this.dicts.length > 0) { this.getDicts(this.dicts) } }, methods: { getDicts(dictTypes) { // 触发字典加载并存储到 Vuex } } } ``` 2. **自定义指令 `v-dict`** 在 `src/directive/dict/index.js` 中实现值到标签的转换: ```javascript Vue.directive(&#39;dict&#39;, { update(el, binding) { const dictType = binding.arg // 字典类型(如 sys_user_sex) const value = binding.value // 当前值(如 0) const dictData = store.state.dict.dictData[dictType] const target = dictData.find(item => item.dictValue === value) el.innerText = target ? target.dictLabel : &#39;&#39; } }) ``` --- ### 四、优势与扩展 1. **优势** - 自动缓存字典数据,减少重复请求 - 通过声明式绑定简化开发(如 `dicts: [&#39;type&#39;]`) - 支持组件和指令两种使用方式 2. **扩展自定义字典** 若需添加新的字典类型,只需: - 后端:在 `sys_dict_type` 和 `sys_dict_data` 表中新增字典数据 - 前端:在组件中声明 `dicts: [&#39;your_dict_type&#39;]` --- 通过这种设计,Ruoyi-Vue 实现了字典数据的高效管理和灵活使用,开发者可以快速实现枚举值的友好展示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

muyi517

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值