vue el-transfer新增拖拽排序功能---sortablejs插件

<template>
  <!-- target-order="unshift"必须设置,如果不设置的话后台穿的value值得顺序会被data重置 -  -->
    <el-transfer ref="transfer" id="transfer" v-model="value" target-order="unshift" :data="datas" filterable :filter-method="menuFilterMethod" filter-placeholder="Please enter button" :titles="['Select', 'Selected']" @change="onChange">
      <span slot-scope="{ option }" class="item"  @dragstart="drag($event,option)">{{ option.label }}</span>
    </el-transfer>
</template>

 

<script>
import Sortable from 'sortablejs'
export default {
  name: 'Transfer',
  props: {
    model: {
      type: Array,
      default: () => {
        return []
      }
    },
    data: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  data() {
    return {
      datas: this.data,
      value: [],
      draggingKey: '',
      menuFilterMethod(query, item) {
        // return item.menuListdata.indexOf(query) > -1
        const regStr = query.replace(/\*/g, '.*')
        const reg = new RegExp(regStr)
        return reg.test(item.label)
      }
    }
  },
  watch: {
    // 监听 弹窗显示, 可以用来写 编辑时的请求接口
    model: function(newVal, oldVal) {
      if (newVal) {
        this.value = newVal
      }
    }
  },
  mounted() {
    const transfer = this.$refs.transfer.$el
    const leftPanel = transfer.getElementsByClassName('el-transfer-panel')[0].getElementsByClassName('el-transfer-panel__body')[0]
    const rightPanel = transfer.getElementsByClassName('el-transfer-panel')[1].getElementsByClassName('el-transfer-panel__body')[0]
    const rightEl = rightPanel.getElementsByClassName('el-transfer-panel__list')[0]
    Sortable.create(rightEl, {
      animation: 100,
      onEnd: (evt) => {
        const { oldIndex, newIndex } = evt
        const temp = this.value[oldIndex]
        if (!temp || temp === 'undefined') {
          return
        }// 解决右边最后一项从右边拖左边,有undefined的问题
  //这里和网上的有点不一样,网上搜到的结果排序是,当前拖拽的元素和拖拽位置的元素互换位置,但是实际上在使用el-transfer有两个问题
  //1.右侧排序value的数组顺序来源于后台穿的数组顺序,实际如果不设置target-order="unshift"的话,展示会按照左侧的数据列顺序展示,导致拖拽排序时顺序乱七八糟
  //2.实际拖拽排序看到的效果是当前拖拽元素拖拽到其他地方,其他地方的元素会下移,而不是调换顺序
        // 去除空字符串
        for (var i = 0; i < this.value.length; i++) {
          if (this.value[i] === '' || this.value[i] === null || typeof (this.value[i]) === 'undefined') {
            this.value.splice(i, 1)
            i = i - 1
          }
        }
        const arr_temp = [].concat(this.value) // 创建一个新的临时数组,用以操作后不变更原数组
        console.log(this.value)
        arr_temp.splice(newIndex, 0, arr_temp.splice(oldIndex, 1)[0]) // 在b位置插入从a位置截取的元素
        this.value = arr_temp
        console.log(this.value)
        this.$emit('update:call-back', this.value)
      }
    })
    const leftEl = leftPanel.getElementsByClassName('el-transfer-panel__list')[0]
    Sortable.create(leftEl, {
      animation: 100,
      onEnd: (evt) => {
        const { oldIndex, newIndex } = evt
        const temp = this.datas[oldIndex]
        this.$set(this.datas, oldIndex, this.datas[newIndex])
        this.$set(this.datas, newIndex, temp)
      }
    })
    leftPanel.ondragover = (ev) => {
      ev.preventDefault()
    }
    leftPanel.ondrop = (ev) => {
      ev.preventDefault()
      const index = this.value.indexOf(this.draggingKey)
      if (index !== -1) {
        this.value.splice(index, 1)
      }
    }
    rightPanel.ondragover = (ev) => {
      ev.preventDefault()
    }
    rightPanel.ondrop = (ev) => {
      ev.preventDefault()
      if (this.value.indexOf(this.draggingKey) === -1) {
        this.value.push(this.draggingKey)
      }
    }
  },
  methods: {
    drag(ev, option) {
      this.draggingKey = option.key
    },
    onChange(value, direction, movedKeys) {
      // console.log(value, direction, movedKeys)
      this.$emit('update:call-back', value)
    }
  }

 

}
</script>
posted @ 2021-07-09 16:57  吃不棒的胖胖糖  阅读(1913)  评论(0编辑  收藏  举报