用两个 vue-element-table 实现类似穿梭框功能

文章讲述了如何在前端使用ElementUI的el-table组件构建一个可以从多个数据源穿梭选择数据的页面,涉及数据候选区和确认区的设计,以及处理全选和异步数据加载的逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 页面需求

在页面上,我需要从多个数据源选择一些数据保存,觉得用穿梭框比较方便,但是element的transfer好像针对单个数据源,并且个人觉得外观上也比较。。所以决定用两个el-table来改造一个穿梭框。页面框架大致分为两个区域:数据候选区、确认区。

数据候选区:通过按钮获取后端数据传入到候选区

数据确认区: 勾选候选区的数据后,实时更新到确认区,最后保存的数据为确认区中勾选的数据

二. 前端代码

数据选中与否的识别是通过唯一的 id,所以下面代码只展示 id。

1. 数据候选区

<div style="height: 30px; border: 1px solid #f5eeee">
	<span style="font-weight: bold;">候选区</span>
</div>
<el-table ref="temp" :data="tableData" height="500" style="width: 100%" 
    border 
    @select="toggleSelect1"
	@select-all="selectAll1">
	<el-table-column type="selection"></el-table-column>
	<el-table-column prop="id" label="id"></el-table-column>
</el-table>

2. 数据确认区

<div style="height: 30px; border: 1px solid #f5eeee">
	<span style="font-weight: bold;">最终确认区</span>
</div>
<el-table ref="last" :data="lastData" height="500" style="width: 100%"
	border
	@selection-change="handleSelectionChange"
	@select="toggleSelect2"
    @select-all="selectAll2">
	<el-table-column type="selection"></el-table-column>
	<el-table-column prop="id" label="id"></el-table-column>
</el-table>

 3. JS 代码

        通过绑定两个表格的checkbox事件,来实现内容穿梭。

// 候选区单行的checkbox点击事件
toggleSelect1(selection, row) {
	if (selection.indexOf(row) >= 0) {
		if (this.lastData.map((v) => v.id).indexOf(row.id) < 0) {
			this.lastData.push(row);
			this.$refs.last.toggleRowSelection(row, true);
		} else {
			var srow = this.lastData.filter((v) => { return v.id == row.id });
			this.$refs.last.toggleRowSelection(srow[0], true);
		}
	} else {
		if (this.lastData.map((v) => v.id).indexOf(row.id) >= 0) {
			var srow = this.lastData.filter((v) => { return v.id == row.id });
			this.$refs.last.toggleRowSelection(srow[0], false);
		}
	}
},

// 确认区单行的checkbox点击事件
toggleSelect2(selection, row) {
	if (selection.indexOf(row) >= 0) {
		if (this.tableData.map((v) => v.id).indexOf(row.id) >= 0) {
			var srow = this.tableData.filter((v) => { return v.id == row.id });
			this.$refs.temp.toggleRowSelection(srow[0], true);
		}
	} else {
		if (this.tableData.map((v) => v.id).indexOf(row.id) >= 0) {
			var srow = this.tableData.filter((v) => { return v.id == row.id });
			this.$refs.temp.toggleRowSelection(srow[0], false);
		}
	}
},

// 候选区全选的checkbox点击事件
selectAll1(selection) {
	if (selection.length == 0) {
		var idlist = this.tableData.map((v) => v.id);
		var srow = this.lastData.filter((v) => { return idlist.indexOf(v.id) >= 0 });
		if (srow) {
			srow.forEach((row) => {
				this.$refs.last.toggleRowSelection(row, false);
			})
		}
	} else {
		var idlist = this.lastData.map((v) => v.id);
		selection.forEach((row) => {
			if (idlist.indexOf(row.id) < 0) {
				this.lastData.push(row);
			}
			this.$refs.last.toggleRowSelection(row, true);
		})
	}
},

// 确认区全选的checkbox点击事件
selectAll2(selection) {
	var idlist = this.lastData.map((v) => v.id);
	var srow = this.tableData.filter((v) => { return idlist.indexOf(v.id) >= 0 });
	if (srow) {
		if (selection.length == 0) {
			srow.forEach((row) => {
				this.$refs.temp.toggleRowSelection(row, false);
			})
		}else{
			srow.forEach((row) => {
				this.$refs.temp.toggleRowSelection(row, true);
			})
		}
	}

},

// 获取确认区勾选的数据
handleSelectionChange(selection) {
    this.savedata= selection;
    this.selectIdList = selection.map((v)=>v.id); // 选中的id列表
},

 4. 异步数据切换数据源

axios.get('127.0.0.1/my_request.php').then((res) => {
	this.tableData = res.data.data;
    // 如果新数据源有数据在确认区已被选中,需在候选区默认也选中
	var rows = this.tableData.filter((v) => { 
        return this.selectIdList.includes(v.id) 
    });
	this.$nextTick(() => {
		rows.forEach((row) => {
			this.$refs.temp.toggleRowSelection(row, true);
		})
	})
}).catch(() => { });

5. 不可选数据

如果数据源中有一些数据不可供选择,第一种方法是在后端筛除,第二种方法是传回前端,但要能识别哪些id不可选择。例如识别出的 id 存在 this.disableIDList 中。接下来在数据候选区的selction列中绑定selectable方法,来确定哪些行可选。

<el-table-column type="selection" :selectable="selectable"></el-table-column>
computed: {
	selectable: function () {
		return (row, index) => {
			if (this.disableIDList.indexOf(row.id) >= 0) {
				return false;
			} else {
				return true
			}
		}
	},
},

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值