1. 程式人生 > >分享一個基於vue2.0+的拖動排序元件

分享一個基於vue2.0+的拖動排序元件

先來個效果圖:
在這裡插入圖片描述

元件的實現是基於改變源資料的陣列位置,所以使用的話必須要對傳進去的源資料做一次深拷貝,操作完成後再傳排序後的陣列回去;
事件是採用了drag系列事件,跟需求和使用者操作習慣比較吻合;
圖示是element-ui裡面的;
過度效果是vue的transition-group標籤實現的,這裡要注意的是transition-group包裹的次級元素一定要有唯一的key,而且依舊要設定transition樣式,否則不會有過度效果;
獲取陣列下標的處理方式不是特別好,希望路過的大神幫忙指點一下,蟹蟹;

下面是原始碼:

<template>
  <ul class="dragSort">
    <transition-group>
      <li
        draggable="true"
        @dragstart="handlerDragstart"
        @drag="handlerDrag"
        @dragend="handlerDragend"
        :id="index"
        v-for="(item, index) in dataList"
        :key="item.a">
        【{{index+1}}】{{item.a}}
        <i class="el-icon-sort"/>
      </li>
    </transition-group>
  </ul>
</template>
<script>
export default {
  props: {
  },
  name: 'dragSort',
  data () {
    return {
      dataList: [
        { a: '測試類目-001' },
        { a: '測試類目-002' },
        { a: '測試類目-003' },
        { a: '測試類目-004' },
        { a: '測試類目-005' },
        { a: '測試類目-006' },
        { a: '測試類目-007' }
      ]
    }
  },
  methods: {
    handlerDragstart (e) {
      const { y, target } = e
      target.style.opacity = '.5'
      target.oriY = y
      target.oriIndex = Number(target.id)
    },
    handlerDrag (e) {
      const { y, target } = e
      if (y === 0) return
      const offset = y - target.oriY
      const length = this.dataList.length
      if (Math.abs(offset) > target.offsetHeight) {
        const index = target.oriIndex
        const copyList = [...this.dataList]
        let targetIndex = index + Math.round(offset / target.offsetHeight)
        if (targetIndex > length - 1) {
          targetIndex = length - 1
        } else if (targetIndex < 0) {
          targetIndex = 0
        }
        const readyToAppend = copyList.splice(index, 1)[0]
        copyList.splice(targetIndex, 0, readyToAppend)
        target.oriIndex = targetIndex
        target.oriY = y
        this.dataList = copyList
      }
    },
    handlerDragend (e) {
      const { y, target } = e
      target.style.opacity = '1'
    }
  }
}
</script>
<style scoped lang="scss">
.dragSort{
  width: 200px;
  list-style: none;
  margin: 0;
  padding: 0;
  li{
    text-align: left;
    border: 1px solid #f1f1f1;
    padding: 10px;
    box-shadow: 0 2px 8px 0 rgba(0, 0, 0, .1);
    border-radius: 5px;
    margin-bottom: 10px;
    cursor: move;
    width: 100%;
    background: #fff;
    transition: all .3s;
    z-index: 1;
    i {
      font-size: 16px;
      color: #409EFF;
      float: right;
    }
  }
}
</style>

轉載請註明出處蟹蟹