您的位置:首页 > Web前端 > Vue.js

Vue 利用后端的数据字典和Map对象实现表格列字段动态转义的处理方案

2021-07-04 18:01 148 查看

1、前言

  Vue中,使用el-table组件,经常遇到列字段转义的问题。常规处理方法有以下两种:

  • 方法1:在模板中使用v-if,直接转义。如:
<el-table-column label="是否学员" prop="isStudent" min-width="7%">
<template slot-scope="scope">
<span v-if="scope.row.participantType == 0">N</span>
<span v-if="scope.row.participantType == 1">Y</span>
</template>
</el-table-column>
  • 方法2:使用formatter,进行转义处理,如:

  在模板中指明使用格式转换器:

<el-table-column label="证件类型" prop="idType" :formatter="idFormatter" min-width="10%"></el-table-column>

  在Javascript中,实现指定的格式转换器:

data() {
return {
// 证件类型列表
idTypeList: [
{idType:1,idTypeName:"身份证"},
{idType:2,idTypeName:"社保卡"},
{idType:3,idTypeName:"驾驶证"},
{idType:4,idTypeName:"护照"},
{idType:5,idTypeName:"临时身份证"},
{idType:6,idTypeName:"工作证"}
],

//其它属性
//...
}
},
methods: {
// 证件类型字段翻译
idFormatter(row, column) {
var value = "";
for (var i = 0; i < this.idTypeList.length; i++){
var item = idTypeList[i];
if (row.idType == item.idType) {
value = item.idTypeName;
break;
}
}
return value;
},
}

  这两种处理方法都有效,但感觉不是很好。

  • 方法1的问题,是需要枚举各种可能性,如果枚举项很多,代码固化,书写是个体力活,且代码很不简洁。另外,灵活性不高,如果后端对该字段增加枚举项,前端也需要修改。

  • 方法2的问题,如果需要字段转义的列较多时,需要定义较多的格式转换器方法。

  因此,推荐使用下面的方案。

2、动态字段转义处理方案

2.1、后端使用系统参数表并提供查询接口

  首先,后端对字段的枚举类型,均使用系统参数表来存储,这样,前后端统一使用同一份数据字典。参见之前的文章:《使用系统参数表,提升系统的灵活性 》。

  然后,后端提供相应的接口,供前端获取指定类别的参数项(枚举项)列表。接口定义如下:

Path: /sysParam/getParameterClass
Method: POST

接口描述:
请求参数:
Headers
参数名称		参数值		  是否必须	示例	备注
Content-Type	application/json  是
Authorization	token		  是			token值
Body
名称		类型		  是否必须	默认值		备注			其他信息
classKey	string		  必须				参数类别key

返回数据:
名称	     类型	         是否必须    默认值  备注	    其他信息
data	     object []	         非必须		    返回数据
item   类型: object
├─ SysParameter类型 各字段,略
code	integer	                 必须		    返回码
message	string	                 必须		    提示信息
additional	object	        非必须		    附加信息,Additional类型,略

2.2、前端获取系统参数的常规方法

  页面中获取系统参数的常规处理方法,如下:

data() {
return {
// 证件类型列表
idTypeList: [],

//其它属性
//...
}
},
created() {
this.getIdTypeList();
},
methods: {
// 证件类型字段翻译
idFormatter(row, column) {
var value = "";
for (var i = 0; i < this.idTypeList.length; i++){
var item = idTypeList[i];
if (row.idType == item.idType) {
value = item.idTypeName;
break;
}
}
return value;
},

// 获取证件类型列表数据
getIdTypeList() {
let _this = this;
this.instance.getParameterClass(this.$baseUrl,{"classKey":"id_type"}).then((response) => {
_this.idTypeList = response.data.data;
});
},
}

  api/index.js中定义instance的接口:

//获取类别信息列表
getParameterClass (baseurl, data) {
var url = baseurl + '/sysParam/getParameterClass';
return instance.post(url, data);
},

  现在的问题,如果获取每个参数类型,都要用一个方法来实现,显得太繁琐,代码不优雅。另外,列字段转义还是使用了格式转换器,因为列表数据只能使用遍历。

2.3、前端开发公共方法来获取系统参数

  现在的方案,字段转义的数据字典由后端定义,这样一来,前端各个页面将会大量调用获取系统参数的接口。因此有必要开发公共方法来获取系统参数。

  参数类别的数据,页面需要两种类型的数据:

  • 列表类型,用于选择框,如查询条件,此时往往需要在列表中增加一项类似“全部类型”的选项,表示忽略此条件。
  • 字典类型,用于表格列字段转义。

  在/src/common/commonFuncs.js中,实现获取系统参数的方法,代码如下:

/**
* 获取参数类别信息列表及字典
* @param {容器对象} parent
* @param {参数类别key} classKey
* @param {列表的属性名} listObjPropName
* @param {字典的属性名} mapObjPropName
* @param {字段数据类型} fieldDatatype
*/
getParameterClass(parent, classKey, listObjPropName, mapObjPropName, fieldDatatype="int"){
parent.instance.getParameterClass(
parent.$baseUrl, {"classKey" : classKey}
).then(res => {
//console.log(res.data);
if (res.data.code == parent.global.SucessRequstCode){
//如果查询成功
//console.log(res.data.data);
if (listObjPropName != undefined && listObjPropName != ""){
//需要输出列表数据
for(var i = 0; i < res.data.data.length; i++){
var item = res.data.data[i];
//往后添加数据,不破坏列表原有数据
parent[listObjPropName].push(item);
}
}
if(mapObjPropName != undefined && mapObjPropName != ""){
//需要输出字典数据
//字典的key要匹配字段类型,由于itemKey为类型为字符串,而字段数据类型一般为整型(枚举值)
//可能需要进行类型转换
//遍历列表数据
for(var i = 0; i < res.data.data.length; i++){
var item = res.data.data[i];
var mapKey;
if (fieldDatatype == "int"){
//字符串转int
mapKey = parseInt(item.itemKey);
}else{
mapKey =item.itemKey;
}
//加入字典
parent[mapObjPropName].set(mapKey,item);
}
}
}else{
alert(res.data.message);
}
}).catch(error => {
alert('查询系统参数失败!');
console.log(error);
});
}

2.4、Vue文件中获取系统参数的用法

  样例Vue文件,模板代码如下:

<template>
<div id="contentwrapper">
<el-form ref="form" :model="formData" label-width="80px"><el-card>
<el-row>
<!--占整行-->
<el-col :span="24">
<h5 class="heading" align=left>用户管理 / 用户管理</h5>
<!-- 分隔线 -->
<el-divider></el-divider>
</el-col>
</el-row>
<el-row>
<el-col align="left" :span="6">
<el-button type="primary" size="small" @click="addUser">
<i class="el-icon-circle-plus"></i>添加用户
</el-button>
</el-col>

<!-- 查询条件 -->
<el-col align="left" :span="12">
<el-form-item label="用户类型:" label-width="100px">
<el-select v-model="formData.userTypeLabel" size="small" @change="selectUserType">
<el-option
v-for="(item,index) in userTypeList"
:key="index"
:label="item.itemValue"
:value="item"
/>
</el-select>
</el-form-item>
</el-col>
<el-col align="right" :span="6">
<el-button type="primary" size="small" @click="queryUsers">
<i class="el-icon-search"></i>查询
</el-button>
</el-col>
</el-row>

<!-- 用户列表数据 -->
<el-table :data="userInfoList" border stripe :row-style="{height:'30px'}" :cell-style="{padding:'0px'}" style="font-size: 10px">
<el-table-column label="用户ID" prop="userId"></el-table-column>
<el-table-column label="用户类型" width="80px" prop="userType">
<template slot-scope="scope">
<span>{{userTypeMap.get(scope.row.userType).itemValue}}</span>
</template>
</el-table-column>
<el-table-column label="登录名" prop="loginName"></el-table-column>
<el-table-column label="真实名称" prop="userName"></el-table-column>
<el-table-column label="手机号码" prop="phoneNumber" width="80px"></el-table-column>
<el-table-column label="EMail" prop="email" width="80px"></el-table-column>
<el-table-column label="操作" width="60px">
<template slot-scope="scope">
<el-tooltip class="item" effect="dark" content="编辑" placement="left-start">
<el-button size="mini" type="primary" icon="el-icon-edit" circle @click="editUser(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-card>
</el-form>
</div>
</template>

  模板代码中,有一个用户类型的选择框,还有表格中对用户类型数据列进行转义处理。注意数据列转义处理的处理代码:

<el-table-column label="用户类型" width="80px" prop="userType">
<template slot-scope="scope">
<span>{{userTypeMap.get(scope.row.userType).itemValue}}</span>
</template>
</el-table-column>

  这个代码相当简洁。

  下面是javascript中与系统参数获取与设置相关的代码:

data() {
return {
formData : {
//查询信息
queryInfo:{
userType  : 0,
deleteFlag: 0,
pagenum   : 1,
pagesize  : 10
},

//用户类型选择框当前选择项的显示值
userTypeLabel : "所有类型"
},

//用户类型参照表,构造初始数据项
userTypeList  : [
{
itemKey   : "0",
itemValue : "所有类型"
}
],

//用户类型字典
userTypeMap : new Map(),

//查询到的用户信息列表
userInfoList:[],

//新增编辑对话框可见标记
editVisible:false,

show:false
}
},
created() {
// ==========================================
// 获取需要的系统参数,注意:getParameterClass方法是异步加载数据的。
// 如需要打印观察,需要通过watch来处理

// 获取用户类型的参数类别
this.commonFuncs.getParameterClass(this,"user_type","userTypeList","userTypeMap");
},
watch:  {
userTypeList  : {
handler(newValue, oldValue){
//获取数据后,设置选择框的初始值;
this.$set(this.formData,'userTypeLabel',this.userTypeList[0].itemValue);
},
immediate: true
},
userTypeMap  : {
handler(newValue, oldValue){
console.log(newValue);
},
immediate: true
}
},
methods: {
//查询用户信息列表
queryUsers(){
let _this = this;
this.instance.queryUsers(
this.$baseUrl,this.formData.queryInfo
).then(res => {
console.log(res.data);
if (res.data.code == this.global.SucessRequstCode){
//如果查询成功
_this.formData.pageInfo.total = res.data.data.length;
_this.userInfoList = res.data.data;
}else{
alert(res.data.message);
}
}).catch(error => {
alert('查询失败!');
console.log(error);
});
},

//用户类型选择
selectUserType(item){
console.log(item);
this.$set(this.formData.queryInfo,'userType',parseInt(item.itemKey));
this.$set(this.formData,'userTypeLabel',item.itemValue);
},
}

  注意事项:

  1. 由于数据是动态获取的,但vue 无法监听动态新增的属性的变化,需要用 $set 来为这些属性赋值。否则选择框的选择选项后,当前值的显示不会改变。

    //用户类型选择
    selectUserType(item){
    console.log(item);
    this.$set(this.formData.queryInfo,'userType',parseInt(item.itemKey));
    this.$set(this.formData,'userTypeLabel',item.itemValue);
    },
  2. 为了使得选择框的选择能够生效,

    <el-form ref="form" :model="formData" label-width="80px">

    的model设置必须包含选择框的当前选择项的显示值,即:

    <el-form-item label="用户类型:" label-width="100px">
    <el-select v-model="formData.userTypeLabel" size="small" @change="selectUserType">
    <el-option
    v-for="(item,index) in userTypeList"
    :key="index"
    :label="item.itemValue"
    :value="item"
    />
    </el-select>
    </el-form-item>

    el-select的v-model即userTypeLabel必须在form的model中,也就是说formData必须包含userTypeLabel。

  3. 在data部分,定义了用户类型的列表和字典对象。其中用户类型列表用于选择框,字典用于表格数据列字段转义。其中,用户类型列表设置了初始项,表示全部类型。(也可以约定由后端的系统参数表来统一定义,这样前端无需设置初始项)。

    //用户类型参照表,构造初始数据项
    userTypeList  : [
    {
    itemKey   : "0",
    itemValue : "所有类型"
    }
    ],
    
    //用户类型字典
    userTypeMap : new Map(),
  4. 系统参数的获取方法,一般在页面加载时获取:

    created() {
    // ==========================================
    // 获取需要的系统参数,注意:getParameterClass方法是异步加载数据的。
    // 如需要打印观察,需要通过watch来处理
    
    // 获取用户类型的参数类别
    this.commonFuncs.getParameterClass(this,"user_type","userTypeList","userTypeMap");
    },

    调用公共方法getParameterClass,可以一次性获取某个参数类别的列表和字典数据,允许获取某一种类型数据,只需将另一个参数设为空字符串即可。

    列表和字典的参数值,必须在data中声明的属性名,并且类型要匹配。

    从代码量看,获取系统参数的调用是相当简洁的。

  5. 在系统参数获取成功后的处理,一般在watch中实现。

    watch:  {
    userTypeList  : {
    handler(newValue, oldValue){
    //获取数据后,设置选择框的初始值;
    this.$set(this.formData,'userTypeLabel',this.userTypeList[0].itemValue);
    },
    immediate: true
    },
    },

    监视到userTypeList数据加载完毕后,设置用户类型选择框的初始选择项。

2.5、效果图

  运行Vue,在浏览器输入相应url,页面显示如下:

  可以看到列表中用户类型数据列已经转义显示。

2.6、其它

  如果数据字典不是由后台提供,而是前端固化,则只需在data中声明userTypeMap为字典类型,然后在created事件中,完成初始化即可。

  这种情况下,数据列转义仍然有效。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐