当前位置:   article > 正文

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

element transfer

不知道大家有没碰到用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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

这两个table其实也就是百度上的自定义table功能。而tableKey则是从父组件通过props传进来的数组。

tableKey: [{
                name: '主账号',
                value: 'accountNames',
                label: 100
              },{
                name: '主账号别名',
                value: 'accountNbrs',
                label: 100
              }],
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143

这里是在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

2022年2月21日 尝试已把组件功能打包发布到npm 中了,https://www.npmjs.com/package/ge-transfer readme中使用说明以及参数说明直接拉注释,所以显示有些混乱,初始化数据得在mounted中,不能直接在使用该组件的父组件中的data 中定义,因为子组件还没渲染完成,所以展示不了初始数据。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/363736
推荐阅读
相关标签
  

闽ICP备14008679号