不知道大家有沒碰到用elementui中transfer組件功能,裏面的列表其實是el-checkbox-group。這就有個問題,如果列表中有多列數據需要區分顯示就沒辦法了,畢竟是el-checkbox。但是這種需求的功能一般項目都不多。
下面這個是我改造的效果
初始數據也可以在右邊已選框中。如果有多列可以很好區分開,同時支持待選列表也就是左邊table搜索功能。
基本實現思路:
1.左右兩邊各一個table列表,左邊代表待選區,右邊代表已選區。
2.通過table自帶多選功能把勾選中的值通過中間按鈕push到右邊table綁定的數組中,同時左邊刪除被勾選的item。
3.右邊刪除功能刪除右邊該行的數據同時左邊push回這條數據。
4.右邊每次有數據變動(添加或者刪除)時,需要$emit數據到父組件進行數據提交更新。(transfer組件是作爲子組件使用的)
5.搜索功能是可選的,左邊列表數組通過Input搜索框綁定的v-model值來indexOf()。
5.1這裏需要注意的是,檢索出來的列表數據實時更新。所以在刪除檢索值要判斷是否刪除所有輸入值(我這裏最後刪除到” “空值時會出現重複數據,所以加個判斷)。
6.因爲是子組件,所以初始值是通過父組件傳遞的。但傳遞數據可能會動態更新,所以用watch監聽props內容。(注意:watch在組件通過v-if創建時並不會執行)
下面開始上代碼:
HTML:
<template>
<div style="border: 1px solid #cccccc;padding: 10px">
<div style="dispaly:inline" v-if="hasSearch">
<el-form ref="inputRefs" :model="searchInput" :inline="true">
<el-form-item prop="tableDataName">
<el-input icon="search" v-model="searchInput.tableDataName" :placeholder="searchHolder?searchHolder:'請輸入搜索內容'" style="width:240px" @change="realTime"></el-input>
</el-form-item>
</el-form>
</div>
<el-row>
<el-col :span="10">
<el-table
:data="tableData"
border
height="280"
style="width: 100%;margin-bottom: 0px"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="40">
</el-table-column>
<el-table-column v-for="(item, key) in tableKey"
:key="key"
:prop="item.value"
:label="item.name"
:width="item.width"
show-overflow-tooltip
>
</el-table-column>
</el-table>
</el-col>
<el-col :span="4">
<div style="margin-top: 100%;margin-left:25%;margin-right:25%">
<!-- <el-button @click="selectItems">獲取選中數據</el-button> -->
<el-button type="primary" @click="selectItems" icon="icon el-icon-d-arrow-right"></el-button>
</div>
</el-col>
<el-col :span="10">
<el-table
:data="resultData"
height="280"
style="width: 100%;margin-bottom: 0px"
border
>
<el-table-column v-for="(item, key) in tableKey"
:key="key"
:prop="item.value"
:label="item.name"
:width="item.width"
show-overflow-tooltip
>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
size="mini"
type="danger"
@click.native.prevent="handleDelete(scope.$index, scope.row,resultData)">刪除</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</div>
</template>
這兩個table其實也就是百度上的自定義table功能。而tableKey則是從父組件通過props傳進來的數組。
tableKey: [{
name: '主賬號',
value: 'accountNames',
label: 100
},{
name: '主賬號別名',
value: 'accountNbrs',
label: 100
}],
JS:
<script>
export default {
/**
* 參數說明:
* searchHolder: 搜索框提示的內容
* receiveData: 接收到的數據-待選列表
* hasSearch: 是否需要搜索功能
* tableKey: 字段名
* isCheckValue: 用於初始化數據時,數據在已選的右邊table中-已選列表
* dispatchData: 發送右邊已選table中的數據到父組件事件
*
*
* 使用模板
* <g-transfer :hasSearch="true" :isCheckValue="exportFieldVlue" :searchHolder="pSearchHolder" :receiveData="exportFieldData" @dispatchData="getCurrentNodeTransfer" :tableKey="tableKey"></g-transfer>
*
* $emit提交到父組件上的值是右邊table框中該條的完整數據字段,若想只要某個字段需要在父組件中操作
*
* 修改記錄:
* 2018年8月3日11:15:00
* ge.libin
* 1.初始化賦值等操作原先在created鉤子上賦值,現在改爲用watch監聽方式。同時原先界面有用v-if的方式去掉
* 2.刪除搜索、重置按鈕功能,改爲輸入框實時檢索待選列表數據
* */
props:{
searchHolder:{ type: String},
receiveData:{type: Array,required: true},
hasSearch:{type: Boolean,required: true},
tableKey:{type: Array,required: true},
isCheckValue: {type: Array}
},
data() {
return {
tableData:[],
multipleSelection:[],
resultData:[],
searchInput:{
tableDataName: "", //搜索框綁定值
},
filterTableDataEnd:[],
resetData:[], //用於搜索重置
filterBeforeData:[] //用於存放搜索操作前數據。
}
},
methods:{
realTime(){
// console.log("已執行實時搜索功能");
//每次手動將數據置空,因爲會出現多次點擊搜索情況
this.filterTableDataEnd=[];
//這裏是爲了阻止搜索框刪除完最後一個值時再檢索,數據會重複顯示問題
if(this.searchInput.tableDataName == ""){
this.tableData = this.resetData;
return;
}
this.tableKey.forEach((v,i) => {
this.resetData.forEach((value, index) => {
if(value && value[v.value]){
if(value[v.value].indexOf(this.searchInput.tableDataName)>=0){
this.filterTableDataEnd.push(value)
}
}
});
});
this.tableData = this.filterTableDataEnd;
},
/**
* 跟據當前索引位置刪除數據
* 同時把該條刪除的數據添加到左邊待選table中
*/
handleDelete(index, row,resultData) {
resultData.splice(index,1);//右邊刪除數據
this.filterBeforeData.push(row);
this.resetData = this.filterBeforeData;
//根據刪除後得到的數據再進行一次搜索展示
this.realTime();
this.$emit('dispatchData',this.resultData);
},
handleSelectionChange(val){
this.multipleSelection = val;
},
selectItems:function () {
//等同下一行代碼---數組合並,頻繁使用用concat會造成內存浪費
this.resultData.push.apply(this.resultData,this.multipleSelection);
//把獲取的數據發送到父組件
this.$emit('dispatchData',this.resultData);
//在返回push數據後剩餘的待選列表所有數據賦值到resetData中,然後再在待選列表中顯示檢索刪除被剩餘的數據
this.filterBeforeData = this.overlap(this.filterBeforeData,this.resultData);
this.resetData = this.filterBeforeData;
//刪除左邊被選中的數據,返回待選列表中被剩餘的數據
this.tableData = this.overlap(this.tableData,this.resultData);
},
/**
* 刪除選中item
* @param arr 數據
* @param arr2
* @returns {Array}
*/
overlap:function(arr, arr2) {
var arr3 = new Array();
var index = 0, i = 0, j = 0;
for (i = 0; i < arr.length; i++) {
var has = false;
for (j = 0; j < arr2.length; j++) {
if (arr[i] == arr2[j]) {
has = true;
break;
}
}
if (!has) {
arr3[index++] = arr[i];
}
}
return arr3;
},
},
created(){
// this.tableData = this.receiveData;
// this.resetData = this.tableData;
// if(this.isCheckValue){
// this.resultData = this.isCheckValue;
// //數據初始化時把數據emit到父組件操作方法中
// this.$emit('dispatchData',this.resultData);
// }
},
watch:{
receiveData(val){
this.tableData = val;
this.resetData = val;
this.filterBeforeData =val;
},
isCheckValue(val){
this.resultData = val;
this.$emit('dispatchData',this.resultData);
}
},
computed:{
}
}
</script>
這裏是在watch中把父組件傳遞過來的數據進行初始化賦值。而搜索功能則是通過待選table綁定的數組中的字段來檢索,而字段又是通過tableKey中的值來獲取。(因爲table也是動態的,不知道綁定數組中具體的字段名,所以需要通過tableKey來對應)。
其他的在代碼中也有註釋說明。
如果想看組件文件代碼的話,下載地址:https://download.csdn.net/download/u012138137/10604091