1. 程式人生 > 其它 >vue3中使用draggable外掛實現元素的拖拽,排序,克隆

vue3中使用draggable外掛實現元素的拖拽,排序,克隆

vue2.x版本中利用draggable外掛實現元素的拖拽,排序,克隆的例子網上有很多,這裡不再贅述,有篇文章寫得很不錯,可以參考:https://blog.csdn.net/blue__k/article/details/120202902

但在vue3中,使用vue2.x中draggable的寫法時會報錯:Cannot read property ‘header’ of undefined

這個問題是draggable的版本不對,換為"vuedraggable": "^4.1.0"這個版本就好了

效果圖

安裝

npm i [email protected] --save
npminstallsortablejs--save (拖拽元件依賴sortablejs ,如果專案沒有安裝sortablejs ,需要安裝一下)

引入

import Draggable from 'vuedraggable'

關鍵程式碼

  <Draggable :list="list2" item-key="id" :animation="100" :sort='false' :group="{name: 'article',pull:'clone'}"  @end="end1" class="dragArea1">
      <template #item="{ element }"  >
        <div class="list-complete-item1">
          <
div class="list-complete-item-handle2"> {{element.name}}</div> </div> </template> </Draggable>

注:vue2.x版本Draggable 元件中的配置項寫法(:options="{group:{name:'article',pull:'clone'}, sort:false}")在vue3中不起效,

vue3中需要將裡面的引數單獨進行配置,如::group="{name:'article',pull:'clone'}" :sort='false' 等

兩個盒子之間的內容能夠克隆,需要將兩個group的name配置為一樣,並在group中配置 pull:'clone'

如果不希望第二個盒子中的內容被拖到第一個盒子中,將第二個盒子中的pull改為空:pull:' '

部分Draggable API

 1  group: "name",  // or { name: "...", pull: [true, false, clone], put: [true, false, array] } name相同的組可以互相拖動
 2  sort: true,  // 內部排序列表
 3  delay: 0, // 以毫秒為單位定義排序何時開始。
 4  touchStartThreshold: 0, // px,在取消延遲拖動事件之前,點應該移動多少畫素?
 5  disabled: false, // 如果設定為真,則禁用sortable。
 6  store: null,  // @see Store
 7  animation: 150,  // ms, 動畫速度運動專案排序時,' 0 ' -沒有動畫。
 8  handle: ".my-handle",  // 在列表項中拖動控制代碼選擇器。
 9  filter: ".ignore-elements",  // 不導致拖拽的選擇器(字串或函式)
10  preventOnFilter: true, // 呼叫“event.preventDefault()”時觸發“filter”
11  draggable: ".item",  // 指定元素中的哪些項應該是可拖動的。
12  ghostClass: "sortable-ghost",  // 設定拖動元素的class的佔位符的類名。
13  chosenClass: "sortable-chosen",  // 設定被選中的元素的class
14  dragClass: "sortable-drag",  //拖動元素的class。
15  dataIdAttr: 'data-id',
16  forceFallback: false,  // 忽略HTML5的DnD行為,並強制退出。(h5裡有個屬性也是拖動,這裡是為了去掉H5拖動對這個的影響
17  fallbackClass: "sortable-fallback",  // 使用forceFallback時克隆的DOM元素的類名。
18  fallbackOnBody: false,  // 將克隆的DOM元素新增到文件的主體中。(預設放在被拖動元素的同級)
19  fallbackTolerance: 0, // 用畫素指定滑鼠在被視為拖拽之前應該移動的距離。
20  scroll: true, // or HTMLElement
21  scrollFn: function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) { ... }
22  scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
23  scrollSpeed: 10, // px

全部程式碼

<template>
  <div class="dragList">
    <div class="dragList-list1">
      <h3 style="text-align:center">標籤選擇</h3>
      <Draggable :list="list2" item-key="id" :animation="100" :sort='false' :group="{name: 'article',pull:'clone'}"  @end="end1" class="dragArea1">
        <template #item="{ element }"  >
          <div class="list-complete-item1">
            <div class="list-complete-item-handle2"> {{element.name}}</div>
          </div>
        </template>
      </Draggable>
    </div>

    <div class="dragList-list2">
      <h3 style="text-align:center">拖動至此處</h3>
      <Draggable :list="list1" item-key="id"  :group="{name: 'article',pull:''}"  :disabled="false"  @start="start2" @end="end2" class="dragArea2" >
        <template #item="{ element,index }" >
          <div class="list-complete-item2">
            <div class="list-complete-item-handle">{{element.name}}</div>
            <div>
              <i class="el-icon-delete"  @click="handleDel(index, element.id)"></i>
            </div>
          </div>
        </template>
      </Draggable>
    </div>
  </div>
</template>

<script>
import {ref,reactive} from 'vue'
import Draggable from 'vuedraggable'

export default {
  components: {
    Draggable
  },
  setup() {
    const disabled = ref(false)
    const list1 = reactive([])
    const list2 = reactive(
      [
        {id: 1, name: '標籤1'}, 
        {id: 2, name: '標籤2'}, 
        {id: 3, name: '標籤3'}, 
        {id: 4, name: '標籤4'}, 
        {id: 5, name: '標籤5'}, 
      ]
    )
    const end1 = (ev) => {
      console.log("拖動結束1",ev)
    }
    const start2 = (event) => {
      console.log("開始拖動",event)
    }
    const end2 = (ev) => {
      console.log("拖動結束2",ev)
    }
    const handleDel = (index, id) => {
      list1.splice(index, 1)
      let q = list2.find((value, index, arr) => {
        return value.id === id
      })
    }
    return {
      disabled,
      list1,
      list2,
      end1,
      start2,
      end2,
      handleDel
    }
  }
}
</script>

<style lang="scss"  scoped>
  .dragList{
    width: 500px;
    height:300px;
    padding: 20px;
  }
  .dragList-list1{
    width: 120px;
  }
  .list-complete-item1{
    cursor: pointer;
    font-size: 14px;
    padding: 0 12px;
    display: inline-block;
    margin-bottom: 10px;
    width: 100px;
    height: 50px;
    line-height: 50px;
    border: 1px solid #bfcbd9;
    transition: all 1s;
  }
  .dragArea1{
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
  .dragList-list2{
    margin-top: 20px;
    height: 200px;
    border: 1px solid #8a8a8a;
  }
  .dragArea2{
    display: flex;
    align-items: center;
  }
  .list-complete-item2 {
    cursor: pointer;
    font-size: 14px;
    padding: 0 12px;
    display: inline-block;
    margin: 10px;
    width: 100px;
    line-height: 30px;
    text-align: center;
    border: 1px solid #bfcbd9;
    transition: all 1s;
  }
</style>