- 背景:
- 前端在业务开发过程中,服务端返回一些枚举字段
eg: orderStatu: 1 表示已完成 2 表示已取消 3表示已发货
- 需求点:
- 前端在新增时 【orderStatu】 字段 需要上传【1、2、3】
- 前端在详情时 【orderStatu】需要展示成【已完成、已取消、已发货】
- 解决方案
-
方案1:通过过滤器实现回显枚举
- 生成枚举映射中心
const codeSet = { orderStatusMap: [ { id: 1, name: "已完成" }, { id: 2, name: "已取消" }, { id: 3, name: "已发货" } ] }; export default codeSet;- 业务代码中使用
<template> <div> <!-- 在select中使用 --> <el-select v-model="ruleForm.orderStatus" placeholder="请选择订单状态"> <el-option v-for="item in orderStatusList" :key="item.id" :value="item.name" :label="item.id"></el-option> </el-select> <!-- 通过过滤器回显映射 --> <span>{{ details.orderStatus | orderStatusStr }}</span> </div> </template> <script> import codeSet from "./data/codeSet"; import { arrayFind } from "@/utils/index"; export default { name: "test", filters: { // 订单状态过滤器 orderStatusStr: function(val) { let result = arrayFind(orderStatusList, "id", val); if (result) { return result.name; } else { return ""; } } }, data() { return { orderStatusList: codeSet.orderStatusMap }; }, }; </script>辅助函数
/** 根据数组对象某个属性的值筛选出符合要求的数组元素 * @param {Array} arr 过滤的数组 * @param {String} attr 数组对象中的某个属性 * @param {String} val 具体某个属性的值 * @result {Object} 返回找到的对象元素 * * */ export function arrayFind(arr, attr, val) { if (!(arr instanceof Array)) { return []; } let result = arr.find(value => value[attr] === val); if (result) { return result; } else { return ""; } } -
方案2:通过计算属性实现回显枚举
- 生成枚举映射中心
const codeSet = { authStatusMap: [ { id: 0, name: "未实名" }, { id: 1, name: "已实名" } ] }; export default codeSet;- 业务代码中使用
<template> <div> <!-- 在select中使用 --> <el-select v-model="ruleForm.orderStatus" placeholder="请选择订单状态"> <el-option v-for="item in orderStatusList" :key="item.id" :value="item.name" :label="item.id"></el-option> </el-select> <!-- 计算属性回显映射 --> <span>{{ orderStatusStr }}</span> </div> </template> <script> import codeSet from "./data/codeSet"; export default { name: "test", data() { return { orderStatusList: codeSet.orderStatusMap }; }, computed: { orderStatusStr() { return function(val) { const { orderStatusList } = codeSet; const curItem = orderStatusList.find(x => x.id == val); return curItem.name; }; } }, }; </script> -
方案3:通过混入实现回显枚举
- 生成枚举映射中心
const codeSet = { orderStatusList: [ { id: 1, name: "已完成" }, { id: 2, name: "已取消" }, { id: 3, name: "已发货" } ] }; export default codeSet;- 业务代码中使用
<template> <div> <!-- 在select中使用 --> <el-select v-model="ruleForm.orderStatus" placeholder="请选择订单状态"> <el-option v-for="item in orderStatusList" :key="item.id" :value="item.name" :label="item.id"></el-option> </el-select> <!-- 混入全局函数回显映射 --> <span>{{ getEnumValueName("orderStatusList", scope.row.authStatus) }}</span> </div> </template> <script> import codeSet from "./data/codeSet"; import enumMixin from "@/mixins/enum.js"; export default { name: "test", props: {}, components: {}, mixins: [enumMixin], data() { return { orderStatusList: codeSet.orderStatusMap }; }, computed: {}, watch: {}, methods: {}, created() {}, mounted() {} }; </script> <style lang="scss" scoped></style>辅助函数
// 导入数据 import csrCodeSets from '@/data/codeSet' export default { data() { return { enumData: { ...csrCodeSets } } }, methods: { getEnumValueName(key, id) { if (!key) return false const currentItemList = this.enumData[key] const findItem = currentItemList.find(x => x.id == id) if (findItem) { return findItem.name || '' } return '' } } } -
方案4:通过工厂设计模式实现回显枚举
- 通过工厂函数生成枚举映射中心
import enumFactory from "@/utils/enumFactory"; export const orderStatusEnum = enumFactory("订单状态枚举", [ { value: "1", label: "已完成" }, { value: "2", label: "已取消" }, { value: "3", label: "已发货" } ]);- 业务代码中使用
<template> <div> <!-- 在select中使用 --> <el-select v-model="ruleForm.orderStatus" placeholder="请选择订单状态"> <el-option v-for="item in orderStatusList.enums" :key="item.id" :value="item.name" :label="item.id"></el-option> </el-select> <!-- 通过工厂函数回显映射 --> <span>{{ orderStatusList.getLabelByValue(detailRes.orderStatus) }}</span> </div> </template> <script> import orderStatusList from "./data/codeSet"; export default { name: "test", props: {}, components: {}, data() { return { orderStatusList }; } }; </script>工厂函数
/* * 枚举工厂函数 * @param { name } 语意化枚举名称,根据需要可以不要 * @param { enums } 枚举对象 */ function enumFactory(name, enums) { const labels = enums.map(item => item.label); const values = enums.map(item => item.value); const colors = enums.map(item => item.color); return { name, labels, values, enums, getValueByLabel(label) { return values[labels.indexOf(label)]; }, getLabelByValue(value) { return labels[values.indexOf(value)]; }, getColorByValue(value) { return colors[values.indexOf(value)]; }, getItemByValueOrLabel(valueOrLabel) { let index = values.indexOf(valueOrLabel); if (index < 0) { index = labels.indexOf(valueOrLabel); } return enums[index]; }, canOperation(valueOrLabel, operation) { const operations = this.getItemByValueOrLabel(valueOrLabel)?.operations; return operations && operations.indexOf(operation) !== -1; } }; } export default enumFactory; /* const orderStatusEnum = enumFactory('orderStatus', [ { value: 0, label: '已完成', color: green, operations: ['add', 'detail'] }, { value: 1, label: '待支付', color: orange, operations: ['edit', 'cancel'] }, { value: 2, label: '已取消', color: gray, operations: ['detail'] } ]); */
- 总结
- 以上几种解决方案都能解决业务需求,个人倾向第四种。对业务类入侵小,相对优雅