在 Vue 项目中添加字典翻译工具(二)

封装字段翻译组件,可以格式化字典、枚举、字段
优点: 使用简单,一次配置多次使用,缓存降低后端请求次数,扩展性强

没有缓存时造成单页面多次请求解决方法: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)

下面是使用方法

字段格式化工具(可以格式化字典、枚举、字段)

1. 添加参数

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 是否字典,开启将请求后端字典
class
属性 类型 说明
Enum 枚举 用以匹配后端枚举
Dict 字典 用以匹配后端字典
Field 字段 用以匹配后端字段
2. 使用
格式化

在需要格式化的地方,使用组件 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>
默认插槽

用以自定义追加数据

你可能感兴趣的:(vue,vue.js,javascript,前端)