封装字段翻译组件,可以格式化字典、枚举、字段
优点: 使用简单,一次配置多次使用,缓存降低后端请求次数,扩展性强
没有缓存时造成单页面多次请求解决方法:axios添加缓存请求,防止多次请求,单页面多个同一组件造成多次请求解决方案
store 的 fieldFormat.js(这里用的store的modules)
export default {
namespaced: true,
state: {
types: {}
},
mutations: {
ADD_TYPE: (state, params) => {
state.types[params.type] = params.value;
}
}
}
Dict.js
/**
* 字典,用以匹配后端字典
*/
export default class Dict {
constructor(serve) {
this.serve = serve;
this.id = "dictValue";
this.label = "dictLabel";
this.isDict = true;
}
}
Enum.js
/**
* 枚举,用以匹配后端枚举
*/
export default class Enum {
constructor(serve) {
this.id = "code";
this.label = "name";
this.isEnum = true;
this.serve = serve;
}
}
Field.js
/**
* 字段,用以匹配后端字段
*/
export default class Field {
constructor(serve, id, label, method, dataField) {
this.serve = serve;
this.id = id;
this.label = label;
if (method) {
this.method = method;
}
if (dataField) {
this.dataField = dataField;
}
}
}
formatOptions.js
import * as vehicleTypeService from "@/api/bayonet/vehicleType";
import Enum from "./Enum";
import Dict from "./Dict";
import Field from "./Field";
/**
* 字段格式化组件参数
*
* @param serve 请求地址或请求方法或枚举类型,请求方法可以是api中的,必须是Function: () => Promise格式
* @param id 请求后的数据列表字段,用于匹配那一条数据
* @param label 请求后的数据列表字段,用于自动格式化字段
* @param method 请求方式,默认get
* @param dataField 请求后的data字段,默认data
* @param isEnum 是否枚举,开启将请求后端枚举
* @param isDict 是否字典,开启将请求后端字典
*/
export default {
// 车辆类型
vehicleType: new Field(vehicleTypeService.getList, "vehicleTypeId", "name"),
// 审批状态
approvalStatusEnum: new Enum("com.yunku.project.entryApplication.enums.ApprovalStatus"),
// 申请类型
applicationTypeEnum: new Enum("com.yunku.project.entryApplication.enums.ApplicationType"),
vehicle_enter_status: new Dict("vehicle_enter_status")
}
FieldFormat.vue
<template>
<div>
<template v-if="label && data && !hasSlot">{{ data[label] }}template>
<slot>slot>
<slot name="format" :data="data">slot>
<slot name="list" :list="list">slot>
div>
template>
<script>
import request from '@/utils/request'
import {getDicts as getDicts} from '@/api/system/dict/data';
import formatOptions from "./formatOptions";
export default {
name: "FieldFormat",
props: {
value: [String, Number],
type: String,
params: Object
},
data() {
return {
enumUrl: 'common/utility/getEnumList',
data: undefined,
list: [],
serve: undefined,
id: undefined,
label: undefined,
method: 'get',
dataField: 'data',
isEnum: false,
isDict: false
}
},
computed: {
fieldFormats() {
// 获取vuex中缓存的数据
return this.$store.state.fieldFormat.types;
},
hasSlot() {
// 判断有没有插槽(默认插槽除外)
return (this.$scopedSlots && (!!this.$scopedSlots.list || !!this.$scopedSlots.format))
|| (this.$slots && (!!this.$slots.list || !!this.$slots.format));
}
},
watch: {
type: {
handler(n) {
// 类型改变时重新获取数据
if (n) {
this.getData();
}
}
},
value: {
handler(n) {
// 值改变时重新解析
if (n) {
this.format();
}
}
}
},
methods: {
/**
* 解析
*/
format() {
// 在列表中查找对应数据
const list = this.list;
if (list && list.length > 0) {
this.data = list.find(datum => String(datum[this.id]) === String(this.value));
}
},
/**
* 获取参数
* @returns {string|*}
*/
getOption() {
// 根据type获取option
const option = formatOptions[this.type];
// 赋值属性
Object.assign(this.$data, option);
return option.serve;
},
/**
* 获取数据
*/
getData() {
const method = this.method;
const serve = this.getOption();
// 如果vuex中有当前类型缓存,则取缓存
if (this.fieldFormats[this.type]) {
this.list = this.fieldFormats[this.type];
this.format();
return;
}
if (serve instanceof Function) {
// 如果serve类型为Function,则直接调用取值
serve().then(res => {
this.relRes(res);
});
} else {
if (this.isDict) {
this.relDict();
} else if (this.isEnum) {
this.relEnum();
} else {
const query = {
url: serve,
method: method,
}
// get请求和post请求的参数不一样
query[this.method === 'get' ? 'params' : 'data'] = this.params;
// 请求
request(query).then(res => {
this.relRes(res);
});
}
}
},
/**
* 解析枚举
*/
relEnum() {
request({
url: this.enumUrl,
method: 'get',
params: {
enumType: this.serve
}
}).then(res => {
this.relRes(res);
})
},
/**
* 解析字典
*/
relDict() {
getDicts(this.serve).then(res => {
this.relRes(res);
});
},
/**
* 解析结果
*/
relRes(res) {
let list = this.list = res[this.dataField];
this.$store.commit("fieldFormat/ADD_TYPE", {
type: this.type,
value: list
});
this.format();
}
},
created() {
this.getData();
}
}
script>
main.js添加,可全局使用,不需要页面单独引入
import FieldFormat from "@/components/FieldFormat";
Vue.component('FieldFormat', FieldFormat)
下面是使用方法
在 src/components/FieldFormat/formatOptions.js
中,添加格式化参数
你可以直接使用 JSON 格式来添加参数,也可以使用已定义的 class
export default {
// 车辆类型
vehicleType: {
serve: vehicleTypeService.getList,
id: "vehicleTypeId",
label: "name",
method: 'get',
dataField: 'data'
},
// 审批状态
approvalStatusEnum: new Enum("com.yunku.project.entryApplication.enums.ApprovalStatus")
}
属性 | 类型 | 说明 |
---|---|---|
serve | String 或 Function | 请求地址或请求方法或枚举类型,请求方法可以是api中的,必须是Function: () => Promise格式 |
id | String | 请求后的数据列表字段,用于匹配那一条数据 |
label | String | 请求后的数据列表字段,用于自动格式化字段 |
method | String | 请求方式,默认get |
dataField | String | 请求后的data字段,默认data |
isEnum | Boolean | 是否枚举,开启将请求后端枚举 |
isDict | Boolean | 是否字典,开启将请求后端字典 |
属性 | 类型 | 说明 |
---|---|---|
Enum | 枚举 | 用以匹配后端枚举 |
Dict | 字典 | 用以匹配后端字典 |
Field | 字段 | 用以匹配后端字段 |
在需要格式化的地方,使用组件 field-format
,value为已知数据值, type 为 formatOptions 中添加的名称,另外还有 params 字段用于请求自定义传参
<field-format :value="form.vehicleType" type="vehicleType">field-format>
可以使用插槽实现更多场景的功能,如
<field-format :value="form.vehicleType" type="vehicleType">
<template #format="{data}">{{ data.name }}template>
field-format>
或者获取所有列表,用于遍历
<field-format type="vehicleType">
<template #list="{list}">
<el-select v-model="form.vehicleType">
<el-option
v-for="item in list"
:label="item.name"
:value="item.vehicleTypeId"
:key="item.vehicleTypeId"
>el-option>
el-select>
template>
field-format>
el-form-item>
用以自定义追加数据