天天看點

elementui 使用el-table完成transfer基本功能

不知道大家有沒碰到用elementui中transfer元件功能,裡面的清單其實是el-checkbox-group。這就有個問題,如果清單中有多列資料需要區分顯示就沒辦法了,畢竟是el-checkbox。但是這種需求的功能一般項目都不多。

下面這個是我改造的效果

elementui 使用el-table完成transfer基本功能

初始資料也可以在右邊已選框中。如果有多列可以很好區分開,同時支援待選清單也就是左邊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

後續修改的代碼,下載下傳位址:(新增已選清單搜尋功能,修複搜尋時資料重複問題)

https://download.csdn.net/download/u012138137/10723369

2019年1月28日 功能改進以及一些問題優化(把已選清單中隻能單個删除改為多選轉移,效果同原生el看去一樣,原先單個删除有的代碼隻注釋沒删除同樣可以參考)

https://download.csdn.net/download/u012138137/10880865