[vue+el-transfer] Shuttle frame implementation and bugs encountered have been resolved

I worked overtime last night to write the shuttle frame component, and encountered bugs while writing. Sure enough, only bugs will make you more impressed and worth recording

Packaged into component FreezeTransfer

The effect is as follows:

insert image description here

Mainly refer to this example that can be searched on the official website

insert image description here
First talk about the bug you encountered, and then post the complete code

1. The reason why the el-transfer data source is not displayed after binding, and the filterMethod is wrong
2. Click a single checkbox, all items are selected, and after the data is processed, there is no need to use props conversion:
props="{ key: 'id', label: 'cnName' }" conversion 3. When not selected, the left and right arrows of the middle button do not display 4. The row does not occupy all








1. Let’s talk about the first data source binding. According to the example given on the official website, this is similar to the treeselect example. It needs to convert the format to the format it requires. It’s enough to get data from the interface normally. I’m a component here, so after getting it from the parent page, just pass it to the child component. Listen to the data source in the child component, process the data and bind the data to
insert image description here
insert image description here
treansfer

 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,
    },

The bug encountered here is that the data source on the left already exists, but nothing is displayed, and it is blank.
This pit is caused by the filter-method, because I am a searchable shuttle box. When I took it from the official example, I defined this method first, but I didn’t write anything. I really don’t know if I don’t step on it. It will also affect the display of the data source.

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

2. Click a single check box, and all items are selected. The possible reason is that the ids are all bound to the same, but I checked that it is not the reason. This is also a pit, that is, after the data source is processed, there is no need to write props conversion. No
insert image description here
need

  :props="{
      key: 'id',
      label: 'cnName'
    }"

3. When not selected, the left and right arrows of the middle button are not displayed.
When the official website is not selected,
insert image description here
there is no middle arrow here, which may be affected by the style
insert image description here

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

4. The line is not fully accounted for

/deep/ .el-transfer-panel__item.el-checkbox {
    
    
  width: 100%;
}

5. Every time you open the pop-up window, initialize
because it is displayed in the pop-up window, every time you open the pop-up window, you need to initialize the data.
Define the initTransarr array on the parent component, and set it to empty in the confirmation and cancellation events

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

          this.$emit('handleSure', this.custCodearr)
        }
      } else {
    
    
        this.$emit('handleCancel')
      }
      this.initTransarr = []
      this.$emit('update:visible', false)
    },

6. The use of change events
Here, left-check-change and right-check-change are triggered when the check boxes are checked on the left and right respectively. I have not used them here because of the adjustment of requirements, but they are still reserved.
insert image description here

The change event has three parameters, the current value, the direction of data movement ('left' / 'right'), and the data key array that moves, which is the event of the left and right arrows in the middle

7. Clear the search keywords of a certain panel
insert image description here

parent component

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

          this.$emit('handleSure', this.custCodearr)
        }
      } else {
    
    
        this.$emit('handleCancel')
      }
      this.initTransarr = []
      this.$emit('update:visible', false)
    },

Subassembly

<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>

Guess you like

Origin blog.csdn.net/weixin_49668076/article/details/131303141