vue2.0 + element ui 实现表格穿梭框
element ui 官网里介绍了穿梭框(Transfer),但在实际使用过程中,会出现一些问题:
1.穿梭框里能放置的内容太少,不能满足复杂的业务需求。
2.当选项过多时,穿梭框很难实现分页,左右两个框的分页是联动的,左边翻页了右边也会跟着翻页。若要取消这种关联关系,可参考这篇文章: https://www.cnblogs.com/alice-bj/articles/10703903.html#_label4
本文参考了穿梭框的实现思路,实现了可分页的表格穿梭框,同时涉及到了表格多选与表格里添加表单等知识点。
html结构:
<el-form :inline="true" :model="staffTemp"> <el-form-item label="手机号"> <el-input v-model="staffTemp.phone"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="getStaffList">查找</el-button> </el-form-item> </el-form> <el-row :gutter="20"> <el-col :span="11"> <el-table ref="staffTable" v-loading="listLoading" :key="tableKey" :data="staffList" border fit highlight-current-row @selection-change="handleStaffChange" > <el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column> <el-table-column label="手机" align="center"> <template slot-scope="{row}"> <span>{{ row.phone }}</span> </template> </el-table-column> <el-table-column label="昵称" align="center"> <template slot-scope="{row}"> <span>{{ row.nickName }}</span> </template> </el-table-column> </el-table> </el-col> <el-col :span="2" style="text-align:center;"> <el-button @click="addStaff" type="primary" :disabled="!staffData.length" icon="el-icon-arrow-right" circle ></el-button> <el-button @click="removeStaff" type="primary" :disabled="!selectedStaffData.length" icon="el-icon-arrow-left" circle style="margin-left: 0;margin-top: 10px;" ></el-button> </el-col> <el-col :span="11"> <el-table ref="selectedStaffTable" v-loading="listLoading" :key="tableKey" :data="selectedStaffList" border fit highlight-current-row @selection-change="handleSelectedStaffChange" > <el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column> <el-table-column label="手机" align="center"> <template slot-scope="{row}"> <span>{{ row.phone }}</span> </template> </el-table-column> <el-table-column label="昵称" align="center"> <template slot-scope="{row}"> <span>{{ row.nickName }}</span> </template> </el-table-column> <el-table-column label="类型" align="center"> <template slot-scope="{row}"> <el-select class="filter-item" placeholder="请选择" v-model="row.staffTypeId"> <el-option v-for="item in staffOptions" :key="item.key" :label="item.display_name" :value="item.key" ></el-option> </el-select> </template> </el-table-column> </el-table> </el-col> </el-row>
js部分:
data() { return { listLoading: true, staffTemp: { phone: "", nickName: "", staffTypeId: "" }, staffList: [], selectedStaffList: [], staffData: [], selectedStaffData: [], tableKey: 0, rowKey: "rowKey", staffOptions: [ { key: 28, display_name: "补货员" }, { key: 29, display_name: "测试员" } ], } }, methods: { // 从后台获取左边表格的数据 getStaffList() { fetchStaffList(this.staffTemp).then(res => { if (res.value.staff.length === 0) { alert("查无此人"); } this.staffList = res.value.staff; }); }, // 将左边表格选择项存入staffData中 handleStaffChange(rows) { this.staffData = []; if (rows) { rows.forEach(row => { if (row) { this.staffData.push(row); } }); } }, // 左边表格选择项移到右边 addStaff() { setTimeout(() => { this.$refs["staffTable"].clearSelection(); this.$refs["selectedStaffTable"].clearSelection(); }, 0); let repeat = false; this.selectedStaffList.forEach(item => { if (this.staffData[0] && item.phone === this.staffData[0].phone) { repeat = true; alert("此员工已添加"); return; } }); if (repeat === false) { this.staffData.forEach(item => { this.selectedStaffList.push(item); }); for (let i = 0; i < this.staffList.length; i++) { for (let j = 0; j < this.staffData.length; j++) { if ( this.staffList[i] && this.staffData[j] && this.staffList[i].phone === this.staffData[j].phone ) { this.staffList.splice(i, 1); } } } } }, // 右边表格选择项移到左边 removeStaff() { setTimeout(() => { this.$refs["staffTable"].clearSelection(); this.$refs["selectedStaffTable"].clearSelection(); }, 0); this.selectedStaffData.forEach(item => { this.staffList.push(item); }); for (let i = 0; i < this.selectedStaffList.length; i++) { for (let j = 0; j < this.selectedStaffData.length; j++) { if ( this.selectedStaffList[i] && this.selectedStaffData[j] && this.selectedStaffList[i].phone === this.selectedStaffData[j].phone ) { this.selectedStaffList.splice(i, 1); } } } }, // 将右边表格选择项存入selectedStaffData中 handleSelectedStaffChange(rows) { this.selectedStaffData = []; if (rows) { rows.forEach(row => { if (row) { this.selectedStaffData.push(row); } }); } }, // 提交 modifyStaff() { let isEmpty = false; this.selectedStaffList.forEach(item => { if (!item.staffTypeId) { alert("请选择类型"); isEmpty = true; return; } }); if (isEmpty === false) { editStaff(this.selectedStaffList, this.deviceQuery.id).then(res => { this.staffListVisible = false; this.$notify({ title: "成功", message: "修改成功", type: "success", duration: 2000 }); }); } } }
多选表格:手动添加一个 el-table-column,设type
属性为 selection 即可;当选择项发生变化时会触发 selection-change 事件,并将选择项作为参数传入。在这里,我们将左边表格的选择项缓存在staffData中,右边表格的选择项缓存在 selectedStaffData 中。
在移动选择项时,一是要将自身的该项删除,二是要将该项放入对方列表中(需要去重)。
关于分页功能可在左右两个表格分别添加,互不影响,具体可参考我之前的博客 https://www.cnblogs.com/zdd2017/p/11153527.html