vue实现下拉框的多选功能(附后端处理参数)
作者:【金融科技蚂蚁】
本次演示共涉及三个界面,一个是主表用于展示数据的,一个是表单用于新增数据的,另一个则是编辑用于修改表格数据的,先上效果图:
1、主表界面(数据来源于数据库查表返回):
<el-table :data="tableData" border> <el-table-column type="index" label="序号"></el-table-column> <el-table-column label="姓名" prop="name"></el-table-column> <el-table-column label="爱好" prop="stringHobby"></el-table-column> </el-table>
2、新增数据界面(点击新增按钮触发):
如果要实现对“爱好”这一属性进行下拉框多选,那么前端核心代码可这么写:
//html部分 <el-dialog title="新增" :visible.sync="addDialog"> <el-form-item label="爱好:"> <el-select v-model="formData.hobby" multiple> <el-option v-for="item in hobbyList" :key="item.value" :label="item.label" :value="item.value" ></el-option> </el-select> </el-form-item> </el-dialog> //js部分 export default { data() { return { addDialog: false, formData: [], hobbyList: [ { value: "1", label: "篮球" }, { value: "2", label: "排球" }, { value: "3", label: "足球" } ] } } }
如上图所示,你选择了篮球和排球,那么篮球和排球所对应的码值“1”和“2”就会存入hobby这个属性中,此时formData.hobby的类型是一个列表,其值为["1", "2"],这个值是要作为参数传到后台作处理的。
3、编辑数据界面(点击编辑按钮触发):
编辑界面要实现下拉框多选功能,和新增界面是类似的,但难点有两点:1、当点击上方的编辑按钮时,如何将主表界面的数据全部且正确地带过去?此时编辑界面的表格数据要和主表界面的数据完全一致并且“爱好”这一列自动选择好,用户可直接在现有的数据上作编辑而不是进去后"爱好"这一列都是空的;2、编辑好后整个表格数据的保存问题会比新增要复杂,这些字段在前端如何处理才能被后台接收且方便保存?
针对难点一,我们会想到将主表中:data="tableData"的tableData赋值给这个编辑表格的:data,但是这样只能将“姓名”带过去,因为这个属性在两个界面都是字符串类型直接映射就好,“爱好”属性则不同,它在主表是字符串,到了编辑表必须转换为字符列表才行。如张三的爱好是足球和篮球,在主表中属性值为"3, 1"(字符串类型),需要转为["3", "1"](字符列表类型),这样系统才能根据你设置的hobbyList中的value-label进行自动匹配,核心代码如下:
//html部分 <el-dialog title="编辑" :visible.sync="editDialog"> <el-table :data="editData" border> <el-table-column type="index" label="序号"></el-table-column> <el-table-column label="姓名" prop="name"></el-table-column> <el-table-column label="爱好" prop="hobby"> <template slot-scope="{ row }"> <el-select v-model="row.hobby" multiple> <el-option v-for="item in hobbyList" :key="item.value" :label="item.label" :value="item.value" ></el-option> </el-select> </template> </el-table-column> </el-table> </el-dialog> //js部分 export default { data() { return { editDialog: false, editData: [], } } methods: { //获取编辑页面的表格数据 edit() { this.editDialog = true; //将主表数据赋到编辑页面的表格数据中 this.editData = this.tableData; //循环获取表格的每条记录 for (let i = 0; i < this.editData.length; i++) { //以下代码的目的是将每条记录的爱好这一属性的类型由字符串转换为列表对象,如替换前为"1,2,3",那么替换后为["1","2","3"] let str = this.editData[i].hobby.split(","); let newArray = []; //循环获取每条记录的爱好集合 for (let j = 0; j < str.length; j++) { newArray.push(str[j]); } this.editData[i].hobby = newArray; } } } }
针对难点二,实现方法就是对表格的每条记录都要处理一下(主要是处理"爱好"这一列),然后做循环逐条存库,此处没必要长篇大论,直接上代码:
//html部分 <el-button @click="editSave" icon="el-icon-edit"> 保存 </el-button> //js部分 export default { methods: { //编辑记录时的保存方法 editSave() { var rows=[] var saveData=[] for(let i=0; i< this.editData.length; i++){ var object = new Object() //获取当前记录的所有属性 rows[i] = this.editData[i] object.name = rows[i].name object.hobby = rows[i].hobby saveData.push(object) } //将数据组合成一个列表对象(savaData)传给后端 axios({ method: "post", url: "/dealData/editData", params: savaData }) .then(function(response) { this.$msgbox({ title: '系统提示', message: response.data.message, type: 'success', }) }) .catch(function(error) { console.log(error) }) } } }
以下是完整的前后端代码,可拿来直接运行:
前端:
<template> <div> <div class="class1"> <el-button @click="addDialog = true" type="primary" size="small" round icon="el-icon-edit" > 新增 </el-button> <el-button @click="edit" type="primary" size="small" round icon="el-icon-edit" > 编辑 </el-button> </div> <div> <el-table class="class2" :header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }" :data="tableData" :show-header="true" :background="true" border width="800px" tooltip-effect="light" > <el-table-column type="index" label="序号" width="100px"> </el-table-column> <el-table-column label="姓名" prop="name" width="200px"> </el-table-column> <el-table-column label="爱好" prop="stringHobby" width="500px"> </el-table-column> </el-table> <el-dialog title="新增" :visible.sync="addDialog" :show-close="true" append-to-body width="30%" center > <div class="class3"> <el-form style="margin-left: 50px"> <el-form-item label="姓名:"> <el-input v-model="formData.name" style="width:400px; margin-left:-70px" ></el-input> </el-form-item> <el-form-item label="爱好:"> <el-select v-model="formData.hobby" multiple style="width:400px;margin-left:-70px" > <el-option v-for="item in hobbyList" :key="item.value" :label="item.label" :value="item.value" ></el-option> </el-select> </el-form-item> </el-form> </div> <div class="class3"> <el-button @click="addSave" type="primary" size="small" round icon="el-icon-edit" > 保存 </el-button> </div> </el-dialog> <el-dialog title="编辑" :visible.sync="editDialog" :show-close="true" append-to-body center > <el-table :header-cell-style="{ 'text-align': 'center' }" :cell-style="{ 'text-align': 'center' }" :data="editData" :show-header="true" :background="true" stripe border tooltip-effect="light" > <el-table-column type="index" label="序号"></el-table-column> <el-table-column label="姓名" prop="name"></el-table-column> <el-table-column label="爱好" prop="hobby"> <template slot-scope="{ row }"> <el-select v-model="row.hobby" multiple style="width:300px"> <el-option width="300px" v-for="item in hobbyList" :key="item.value" :label="item.label" :value="item.value" ></el-option> </el-select> </template> </el-table-column> </el-table> <div class="class3"> <el-button @click="editSave" type="primary" size="small" round icon="el-icon-edit" > 保存 </el-button> </div> </el-dialog> </div> </div> </template> <script> export default { data() { return { addDialog: false, editDialog: false, tableData: [], formData: [], editData: [], hobbyList: [ { value: "1", label: "篮球" }, { value: "2", label: "排球" }, { value: "3", label: "足球" } ] }; }, mounted() { //进入主页面自动获取一次表格数据 this.getData(); }, methods: { //获取主页表格数据 getData() { axios({ method: "post", url: "/dealData/showData", params: {} }) .then(function(response) { this.tableData = response.data; }) .catch(function(error) { console.log(error); }); }, //获取编辑页面的表格数据 edit() { this.editDialog = true; //将主表数据赋到编辑页面的表格数据中 this.editData = this.tableData; //循环获取表格的每条记录 for (let i = 0; i < this.editData.length; i++) { //以下代码的目的是将每条记录的爱好这一属性的类型由字符串转换为列表对象,如替换前为"1,2,3",那么替换后为["1","2","3"] let str = this.editData[i].hobby.split(","); let newArray = []; //循环获取每条记录的爱好集合 for (let j = 0; j < str.length; j++) { newArray.push(str[j]); } this.editData[i].hobby = newArray; } }, //新增记录时的保存方法 addSave() { axios({ method: "post", url: "/dealData/addData", params: { 'name': this.formData.name, 'hobby': this.formData.hobby } }) .then(function(response) { console.log(response.data.message); }) .catch(function(error) { console.log(error); }); }, //编辑记录时的保存方法 editSave() { var rows = []; var saveData = []; for (let i = 0; i < this.editData.length; i++) { var object = new Object(); //获取当前记录的所有属性 rows[i] = this.editData[i]; object.name = rows[i].name; object.hobby = rows[i].hobby; saveData.push(object); } //将数据组合成一个列表对象(savaData)传给后端 axios({ method: "post", url: "/dealData/editData", params: savaData }) .then(function(response) { this.$msgbox({ title: "系统提示", message: response.data.message, type: "success" }); }) .catch(function(error) { console.log(error); }); } } } </script> <style scoped> .class1 { margin-top: 50px; margin-bottom: 50px; } .class2 { width: 800px; margin: auto; } .class3 { margin-top: 50px; text-align: center; } </style>
后端:
@Component @Path("/dealData") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public class DealDataController{ @Path("/showData") @Post public List<personBO> showData (){ //查库将数据导入表格,personBO类需要自己写,至少包含id、name、hobby、stringHobby这四个属性,其中stringHobby属性只做前端展示用 List<personBO> personList = DealDataService.getPageData(); for(personBO person: personList){ String hobby = person.getHobby(); //按照爱好编码依次替换,如替换前为"2,1,3",替换后则为"排球,篮球,足球" String stringHobby = hobby.replace("1","篮球").replace("2","排球").replace("3","足球"); person.setStringHobby(stringHobby) } return personList; } @Path("/addData") @Post public Map<String,String> addData (Map<String, Object> paramMap){ Map<String,String> result = new HashMap<>(); //paramMap对象的hobby属性是列表类型,现将其利用逗号分隔符组合成一个字符串并赋值给stringHobby,然后存入数据库,例如数据库表中hobby列看到的数据为:"1, 2, 3",表示三种球都是该人的爱好 List<String> hobbyList = (List<String>) paramMap.get("hobby"); paramMap.put("stringHobby", StringUtils.join(hobbyList,',')); //在Dao层将数据插入数据库,插入成功返回true,失败返回false,此方法不展开写,注意在Mybatis中写sql语句时不是存paramMap的hobby的值,而是存paramMap的stringHobby的值 boolean str = DealDataDao.insertData(paramMap); if(str){ result.put("statusCode", "1111"); result.put("message", "数据插入成功"); }else{ result.put("statusCode", "0000"); result.put("message", "数据插入失败"); } return result; } @Path("/editData") @Post public Map<String,String> editData (Map<String, List<Map<String,Object>>> paramMap){ Map<String,String> result = new HashMap<>(); //将获取到的表格数据作为对象列表,一个对象对应表格的一条记录 List<Map<String, Object>> dataList = paramMap.get("saveData"); int seccessNum = 0; //对表格中的每条记录进行循环更新 for (Map<String,Object> map: dataList){ //map对象的hobby属性是列表类型,现将其利用逗号分隔符组合成一个字符串并赋值给stringHobby,然后存入数据库,例如数据库表中hobby列看到的数据为:"1, 2, 3",表示三种球都是该人的爱好 List<String> hobbyList = (List<String>) map.get("hobby"); map.put("stringHobby", StringUtils.join(hobbyList,',')); //在Dao层将数据更新至数据库,更新成功返回true,失败返回false,此方法亦不展开写,注意在Mybatis中写sql语句时不是存map的hobby的值,而是存map的stringHobby的值 boolean str = DealDataDao.updateData(map); if(str) { seccessNum++; } } //判断更新成功数是否等于总记录数 if(seccessNum == dataList.size()){ result.put("statusCode", "1111"); result.put("message", "全部数据均更新成功"); }else{ result.put("statusCode", "0000"); result.put("message", "存在更新失败的记录"); } return result; }
数据库表中保存的记录如下(1代表篮球,2代表排球,3代表足球,属性hobby为String类型):
id | name | hobby |
1 | 张三 | 3, 1 |
2 | 李四 | 2 |
3 | 王五 | 1, 3, 2 |
到此这篇关于vue实现下拉框的多选功能(附后端处理参数)的文章就介绍到这了,更多相关vue 下拉框多选内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!