当前位置:   article > 正文

【vue+el-transfer】穿梭框实现及遇到的bug,已解决_vue穿梭框组件

vue穿梭框组件

昨晚加班写的穿梭框组件,一边写一边遇到bug,果然只有bug才会让你印象更深刻,更值得记录

封装成组件FreezeTransfer

效果如下:

在这里插入图片描述

主要参考了官网上可搜索的这个示例

在这里插入图片描述
先说遇到的bug,然后贴完整的代码

1、el-transfer数据源绑定之后不展示,filterMethod不对的原因
2、点单个复选框,所有项都被选中,数据被处理后,不需要再 使用props转换
:props=“{
key: ‘id’,
label: ‘cnName’
}”
转换
3、未选择的时候,中间按钮的左右箭头不显示
4、行没有占全
5、每次打开弹窗的时候,初始化
6、change事件的使用
7、清空某个面板的搜索关键词

1、先说第一个绑数据源,按官网给的示例,这个和treeselect的示例差不多,需要将格式转换成它要求的格式
在这里插入图片描述
在这里插入图片描述
正常从接口获取数据就行,我这里是组件,所以在父页面获取到之后,传到子组件就行,在子组件里监听数据源,处理数据之后给treansfer绑定的data

 dataSource: {
      handler(newVal) {
        this.source = newVal.map(item => {
          let obj = {
            key: item.code,
            code: item.code,
            label: item.cnName,
            disabled: false,
          }

          return obj
        })
        this.$emit('getCode', [])
      },
      deep: true,
      immediate: true,
    },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这里遇到的bug就是左侧的数据源已经有了,但就是什么都不展示,一片空白
这个坑就是filter-method引起的,因为我是可搜索的穿梭框,从官方示例拿过来的时候,先定义了这个方法,但是啥都没写,真的是不踩一下根本不知道这还会影响数据源的展示

:filter-method="filterMethod"
filterMethod(query, item) {
//模糊查询,不区分英文大小写
      return item.key.toUpperCase().indexOf(query.toUpperCase()) > -1 || item.label.indexOf(query) > -1
    },

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2、点单个复选框,所有项都被选中,可能的原因就是id都绑了一样的,但我排查了不是这个原因,这也是个坑,就是数据源处理过了之后,不需要再写props转换了
在这里插入图片描述
不需要

  :props="{
      key: 'id',
      label: 'cnName'
    }"
  • 1
  • 2
  • 3
  • 4

3、未选择的时候,中间按钮的左右箭头不显示
官网未选择的时候
在这里插入图片描述
我这里没有中间的箭头,可能是样式受影响了
在这里插入图片描述

/deep/ .el-button.el-button--primary.is-disabled {
  color: #fff !important;
}
  • 1
  • 2
  • 3

4、行没有占全

/deep/ .el-transfer-panel__item.el-checkbox {
  width: 100%;
}
  • 1
  • 2
  • 3

5、每次打开弹窗的时候,初始化
因为是放在弹窗中展示的,每次打开弹窗要初始化数据
父组件上定义initTransarr数组,在确认及取消事件中置为空

  :initTransarr="initTransarr"
  initTransarr:[]
      /** 弹框确认取消 */
    dialogSure(flag) {
      if (flag === 'sure') {

          this.$emit('handleSure', this.custCodearr)
        }
      } else {
        this.$emit('handleCancel')
      }
      this.initTransarr = []
      this.$emit('update:visible', false)
    },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

6、change事件的使用
这里说下,left-check-change和right-check-change,分别在左侧和右侧勾选复选框的时候触发,我这里因为需求的调整,没用到,但还是保留了
在这里插入图片描述

change事件三个参数,当前值、数据移动的方向(‘left’ / ‘right’)、发生移动的数据 key 数组,就是中间左右箭头的事件

7、清空某个面板的搜索关键词
在这里插入图片描述

父组件

    <FreezeTransfer
      v-if="isTransfer"
      ref="freezeTransfer"
      :visible="visible"
      :dataSource="dataSource"
      :initTransarr="initTransarr"
      @getCode="getCode"
    ></FreezeTransfer>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  data() {
    return {
    visible:false,
      custCodearr: [],
      initTransarr: [],
    }
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
    getCode(arr) {
      this.custCodearr = arr
    },
  • 1
  • 2
  • 3
 /** 弹框确认取消 */
    dialogSure(flag) {
      if (flag === 'sure') {

          this.$emit('handleSure', this.custCodearr)
        }
      } else {
        this.$emit('handleCancel')
      }
      this.initTransarr = []
      this.$emit('update:visible', false)
    },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

子组件

<template>
  <div class="transfer">
    <el-transfer
      v-if="visible"
      ref="transfer"
      filterable
      :filter-method="filterMethod"
      :filter-placeholder="$t('placeholderName.enter')"
      v-model="value"
      :data="source"
      :titles="['可选择', '已选择']"
      @change="handleChange"
      @left-check-change="leftcheckChange($event)"
      @right-check-change="rightcheckChange($event)"
    >
      <span slot-scope="{ option }">{{ option.code }} - {{ option.label }}</span>
    </el-transfer>
  </div>
</template>

<script>
export default {
  name: 'FreezeTransfer',
  props: {
    // 列表显示隐藏
    visible: {
      type: Boolean,
      default: false,
    },
    // 列表数据
    dataSource: {
      type: Array,
      default: () => {
        return []
      },
    },
    // 初始化右侧数据
    initTransarr: {
      type: Array,
      default: () => {
        return []
      },
    },

  },
  data() {
    return {
      source: [], // 总数据
      value: [],
    }
  },
  watch: {

    initTransarr: {
      handler(newVal) {
        this.value = newVal
      },
      deep: true,
    },
    dataSource: {
      handler(newVal) {
        this.source = newVal.map(item => {
          let obj = {
            key: item.code,
            code: item.code,
            label: item.cnName,
            disabled: false,
          }

          return obj
        })
        this.$emit('getCode', [])
      },
      deep: true,
      immediate: true,
    },
  },
  mounted() {},
  methods: {
    filterMethod(query, item) {
      return item.key.toUpperCase().indexOf(query.toUpperCase()) > -1 ||         	item.label.indexOf(query) > -1
    },
    //当前值、数据移动的方向('left' / 'right')、发生移动的数据 key 数组
    handleChange(value, direction, movedKeys) {
      if (direction == 'right') {
        this.$nextTick(() => {
          this.$refs.transfer.clearQuery('left')
        })
      } else if (direction == 'left') {
        this.$nextTick(() => {
          this.$refs.transfer.clearQuery('right')
        })
      }
      var arr = []
      value.forEach(item => {
        arr.push({ code: item })
      })
      this.$emit('getCode', arr)
    },
    leftcheckChange(e) {
      //   console.log(e,'left------');
    },
    rightcheckChange(e) {
    //   console.log(e,'right------');
    },



  },
}
</script>

<style scoped lang="scss">
.transfer {
  width: 100%;
  /deep/ .el-transfer-panel {
    width: 45%;
  }
}
/deep/ .el-button.el-button--primary.is-disabled {
  color: #fff !important;
}
/deep/ .el-transfer-panel__item.el-checkbox {
  width: 100%;
}
/deep/ .el-transfer-panel__list {
  height: 480px !important;
}
/deep/ .el-transfer-panel__body {
  height: 480px !important;
}
</style>

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

闽ICP备14008679号