目录

  • 简单看看el-transfer穿梭框
  • 实现思路
  • 完整代码
  • 结果图


简单看看el-transfer穿梭框

Ant Design Vue Transfer 穿梭框 自由排序_数据

这是一个简单的el-transfer穿梭框,截图自element官网 link 列表1为待选数据,列表2为已选数据,通过选中列表中的数据,点击左移或右移按钮,就可以进行数据的选择和取消选择了。

要注意的是,列表1和列表2的数据其实来源于同一个数组对象,列表1是全部的数据列表,列表2是从列表1中选出来的,这很好理解。但是在实际应用中,有可能需要根据搜索条件的不同,左边的数据是在不断变化的。比如从后台传来的数据要分类,我每次只选择一个分类的数据在左边列表,由于右边列表的数据和左边同源,那么我每次右边要刷新的时候,左边也肯定是要刷新的。所以如果需要展示所有分类的已选数据,这个穿梭框就是不适用的。

还有一个会碰到的问题是,左边的数据源data中,是可以有很多属性的,比如id,和我刚刚提到的分类,而右边得到的数据value是有且只有id这一个属性的,那就不是那么灵活。

能否有一个穿梭框,在具备基本穿梭框功能的同时,能保持右边一直展现所有的已选数据,并且右边的数据也可以有很多属性。

实现思路

1.布局:
首先,穿梭框就是要有一左一右两个div用来放我们的数据,div中的数据用el-tree。要有四个按钮用来绑定事件。

2.功能:
右移add增加选项功能:对左边数据选择完毕之后,按下右移按钮,左边div中相应的选项要禁用,右边div中要出现相应的被选数据。
全部右移addAll功能:按下全部右移按钮,左边数据要全部禁用,右边要出现所有的左边数据,并且要跳过已经被选择过的数据。
左移del功能:右边的div,选择完毕之后,按下左移按钮,左边div中相应数据恢复可选状态,并且右边被选的选项要删除。
全部左移delAll功能:按下全部左移按钮,左边div中全部选项恢复可选状态,并且右边清空。

完整代码

新建一个vue+element项目,直接复制代码过去就能运行

<template>
  <div class="transfer">
    <el-form style="width:800px;">
      <el-row>
        <el-col :span="10">
          <el-input placeholder="这里可以放一些搜索的条件"></el-input>
        </el-col>
        <el-col :span="4">
           <el-button @click="setData">查询</el-button>
        </el-col>
      </el-row>

      <el-row>
        <el-col :span="10">
          <!-- 这里是左边的待选框 -->
          <div class="box" style="overflow:scroll; height:500px; border:1px">
            <el-tree
              :data="leftTree"
              node-key="id"
              ref="leftTree"
              show-checkbox
              default-expand-all
              :props="defaultLeftProps"
              check-on-click-node>
            </el-tree>
          </div>
        </el-col>
        <el-col :span="4">
          <div style="margin:40px"><el-button icon="el-icon-arrow-right" @click="add"></el-button></div>
          <div style="margin:40px"><el-button icon="el-icon-d-arrow-right" @click="addAll"></el-button></div>
          <div style="margin:40px"><el-button icon="el-icon-arrow-left" @click="del"></el-button></div>
          <div style="margin:40px"><el-button icon="el-icon-d-arrow-left" @click="delAll"></el-button></div>
        </el-col>
        <el-col :span="10">
          <!-- 这里是右边的已选框 -->
          <div class="box" style="overflow:scroll; height:500px; border:1px">
            <el-tree 
              :data="rightTree"
              node-key="id"
              ref="rightTree"
              show-checkbox
              default-expand-all
              :props="defaultProps"
              check-on-click-node>
            </el-tree>
          </div>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        leftTree:[], //左边树 待选数据
        defaultLeftProps:{
          children: "children",
          label: "name",
          id: "id",
          disabled: "disabled" //表示是否禁用的状态
        },

        rightTree:[], //右边树 已选数据
        defaultProps:{  
          children: "children",
          label: "name",
          id: "id",
        }
      };
    },
    created(){
      this.init();
    },
    methods: {
      init(){
        //初始化的时候分别获取一下左边树和右边树
        this.getRightTree();
        this.getLeftTree();
      },

      //这里是已选数据的获取方法,应该从后台拿的,这里本地模拟一下
      getRightTree(){
        this.rightTree = [{id:1, name:'选项1'}];
      },

      //获取待选数据的方法
      getLeftTree(){
        this.leftTree = [
          {id:1, name:'选项1'},
          {id:2, name:'选项2'},
          {id:3, name:'选项3'},
          {id:4, name:'选项4'},
          {id:5, name:'选项5'},
          {id:6, name:'选项6'},
          {id:7, name:'选项7'}
        ];

        //对右边树中已有的指标,左边树对应的节点要设置禁用
        for(var i=0; i<this.leftTree.length; i++){   
          for(var j=0; j<this.rightTree.length; j++){
            if(this.leftTree[i].id == this.rightTree[j].id){
                this.leftTree[i].disabled = true;
            }
          }
        }
      },

      //查询页面的方法
      setData(){
        this.getLeftTree();
      },
      
      add(){
        var addArr = [];
        let res = this.$refs.leftTree.getCheckedNodes(); //取得所有被选中的左边的数据
        for(var i=0; i<res.length; i++){
          addArr.push({
            id: res[i].id,
            name: res[i].name
          })
          res[i].disabled = true; //将添加过的选项设置禁用
        }
        for(var i=0; i<addArr.length; i++){ //将选择的选项push进右边树里
            this.rightTree.push(addArr[i]);
        }
        this.$refs.leftTree.setCheckedKeys([]); //将之前选中的节点清除勾选状态
        this.$refs.rightTree.setCheckedKeys([]); //将之前选中的节点清除勾选状态
      },

      addAll(){
        this.$refs.leftTree.setCheckedNodes(this.leftTree);//选中所有左边的数据
        let res = this.$refs.leftTree.getCheckedNodes();//取得所有被选中的左边的数据
        for(var i=0; i<res.length; i++){
          if(res[i].disabled == true){ //如果是已经被选中过的,即已经被禁用的节点,跳过这次push
            continue;
          }
          this.rightTree.push({
            id: res[i].id,
            name: res[i].name
          });
          res[i].disabled = true; //将添加过的选项设置禁用
        }
        this.$refs.leftTree.setCheckedKeys([]); //将之前选中的节点清除勾选状态
        this.$refs.rightTree.setCheckedKeys([]); //将之前选中的节点清除勾选状态
        },

        del(){
            var arr = [];
            let res = this.$refs.rightTree.getCheckedNodes();//取得所有被选中的右边的数据
            for(var i=0; i<res.length; i++){
              arr.push({
                id: res[i].id,
                name: res[i].name
              })
            }
            for(var i=0; i<arr.length; i++){ //根据选中的选项删除rightTree中的数据
              for(var j=0; j<this.rightTree.length; j++){
                if(arr[i].id == this.rightTree[j].id){
                  this.rightTree.splice(j,1);
                  j--;
                }
              }
            }
            for(var i=0; i<arr.length; i++){ //将左边树中,被删除的选项恢复可勾选状态
                for(var j=0; j<this.leftTree.length; j++){
                    if(arr[i].id == this.leftTree[j].id){
                        this.leftTree[j].disabled = false;
                    }
                }
            }
            this.$refs.leftTree.setCheckedKeys([]); //将之前选中的节点清除勾选状态
            this.$refs.rightTree.setCheckedKeys([]); //将之前选中的节点清除勾选状态
            this.setData();//刷新一下
        },
        delAll(){
          this.rightTree = [];
          for(var i=0; i<this.leftTree.length; i++){
            this.leftTree[i].disabled = false;
          }
          this.$refs.leftTree.setCheckedKeys([]); //将之前选中的节点清除勾选状态
          this.$refs.rightTree.setCheckedKeys([]); //将之前选中的节点清除勾选状态
          this.setData();//刷新一下
        },
    }
  };
</script>

结果图

Ant Design Vue Transfer 穿梭框 自由排序_i++_02