vue项目中使用vuedraggable

Posted 渔舟唱晚@

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue项目中使用vuedraggable相关的知识,希望对你有一定的参考价值。

最近在学习一个可视化搭建的项目,里面用的拖拽就是draggable.js。看了几个中文的文档,有很多坑,可能是没有及时更新的原因。

VUe 

建议去看vuedraggable的官方文档,只不过是英文的。官方文档:https://github.com/SortableJS/Vue.Draggable

由于vue3已经是默认版本了,所以vuedraggable也对应vue2.0和3.0有各自的版本,直接使用基本命令安装:

npm install vuedraggable --save

会默认安装2.1左右的版本,由于我的项目是vue3构建的,所以会报错:

就是draggable版本不对,导致错误,版本换位4.1.0的就解决了

npm i vuedraggable@4.1.0 --save 或 yarn add vuedraggable@4.1.0

在官网里专门对vue版本的不同做了对应的解释,在vue2中,

<draggable v-model="myArray" group="people" @start="drag=true" @end="drag=false">
   <div v-for="element in myArray" :key="element.id">element.name</div>
</draggable>
//.vue file:

  import draggable from 'vuedraggable'
  ...
  export default 
        components: 
            draggable,
        ,
  ...

With transition-group:

<draggable v-model="myArray">
    <transition-group>
        <div v-for="element in myArray" :key="element.id">
            element.name
        </div>
    </transition-group>
</draggable>

 而在vue3中,这样写是有问题的,官网提示:

Breaking changes:

  1. Use item slot instead of default to display elements#使用项目槽而不是默认值来显示元素
  2. Provide a key for items using itemKey props#使用itemKey道具为物品提供密钥

变动确实挺大的,写法如下:

From:

<!-- vue 2 version -->
<draggable v-model="myArray">
   <div v-for="element in myArray" :key="element.id">element.name</div>
</draggable>

To:

<draggable v-model="myArray" item-key="id">
  <template #item="element">
    <div>element.name</div>
   </template>
</draggable>

 当使用transition时,现在应该使用tag和componentData来创建transition

From

<!-- vue 2 version -->
<draggable v-model="myArray">
    <transition-group name="fade">
        <div v-for="element in myArray" :key="element.id">
            element.name
        </div>
    </transition-group>
</draggable>

to

<draggable v-model="myArray" tag="transition-group" :component-data="name:'fade'">
  <template #item="element">
    <div>element.name</div>
  </template>
</draggable>

注:在进行clone时,vue2.x版本Draggable 组件中的配置项写法(:options="group:name: 'article',pull:'clone', sort: false")在vue3中不起效,

vue3中需要将里面的参数单独进行配置,如::group="name: 'article',pull:'clone'"     :sort='false'  等。

Sortable 的 VueDraggable 无法正常工作,并将所选项目发送到初始化时的第一个

【中文标题】Sortable 的 VueDraggable 无法正常工作,并将所选项目发送到初始化时的第一个【英文标题】:VueDraggable of Sortable is not working properly and send the choosed item to the first on init 【发布时间】:2020-12-03 04:30:25 【问题描述】:

我在我的 Nuxt 项目中使用 Vue.Draggable。我在一些页面和组件中使用了它,一切都很好。但在我的一个页面上,它给了我一个愚蠢的问题!加载页面时,它将所选项目发送到第一个!之后一切正常!即使我选择和取消选择而不移动,一切正常! 我试图检查选择的数组是否再次正确移动它。 it worked when the chosen item is the first if array but if i choose others than first, on 2nd try it move another item too!! 所以我有点卡住了。

代码如下: 顺便说一句,有些变量和方法是你找不到的,比如cmsListItems。它们被全局添加到我的项目中

模板:

<draggable v-model="myItemsArray" @end="onEnd" @choose="onChoose" @unchoose="onUnChoose" v-bind="getOptions()">
    <transition-group type="transition" name="sortable_transition">
      <categorylistcard v-for="(category, index) in cmsListItems" 
      listtype="cat"
      :key="category.id" 
      :cat="category" 
      :index="index" 
      :showforsub="showForSub"
      :parentarr="parentArr"
      @addnewsub="addNewCat()"
      :sub="true"
      :sublvl="true"
      :sortable="true"
      :btntitle="lang.addsubcat"
      />
    </transition-group>
  </draggable>

脚本:

export default 
    data()
      return
        oldIndex: '',
        newIndex: '',
        dragOptions: 
            ghostClass: "sortable_ghost",
            chosenClass: "sortable_chosen",
            handle: ".sortable_handle",
            disabled: false
        ,
        isMoved: false,
        myItemsArray: [],
        originalItemsArray: [],
        choosedItem: null
      
    ,
    methods:
          // ***** Reorder By Sorting *****\\

          this.isMoved = true
          this.oldIndex = event.oldIndex
          this.newIndex = event.newIndex
          console.log(this.myItemsArray[this.oldIndex])
          console.log(this.myItemsArray[this.newIndex])
          if(this.oldIndex !== this.newIndex)

            this.dragOptions.disabled = true
            let response = await this.axiosGet(`category/reorder/$this.originalItemsArray[this.oldIndex].id/$this.originalItemsArray[this.newIndex].id`)
            if(this.resOk(response.status))
                this.noty(ALERT_TYPE[1], 'ok')
                this.originalItemsArray = this.myItemsArray
                this.isMoved = false
                this.dragOptions.disabled = false
                this.addClassToMovedItems(this.oldIndex)
                this.addClassToMovedItems(this.newIndex)
                this.setCmsListItems(this.myItemsArray)
                // this part is my defected solution
                setTimeout(() => 
                  if(this.myItemsArray[this.oldIndex].id === this.choosedItem.id || this.myItemsArray[0].id === this.choosedItem.id)
                    let arrayOfItems = [...this.originalItemsArray]
                    arrayOfItems.shift()
                    arrayOfItems.splice(this.newIndex,0,this.choosedItem)
                    this.setCmsListItems(arrayOfItems)
                    this.myItemsArray = [...this.cmsListItems]
                  
                , 50);
                // --------------------
            else
                this.isMoved = false
                this.myItemsArray = this.originalItemsArray
                this.dragOptions.disabled = false
                this.addClassToMovedItems(this.oldIndex)
                this.addClassToMovedItems(this.newIndex)
            

          else
            this.isMoved = false
            this.myItemsArray = this.originalItemsArray
            this.dragOptions.disabled = false
            this.addClassToMovedItems(this.oldIndex)
            this.addClassToMovedItems(this.newIndex)
          
          
      ,
      addClassToMovedItems(index)
          if((index == this.oldIndex || index == this.newIndex) && this.isMoved == true)
              return 'sortable_moved'
          else
              return ''
          
      
    ,
    async fetch()
      this.btnLoading = true
      let response = await this.axiosGet(`categories/admin/0/1`)
      if(this.resOk(response.status))
        if(this.notEmpty(response.data))
          this.setCmsListItems(response.data.items)
          this.myItemsArray = [...this.cmsListItems]
          this.originalItemsArray = [...this.cmsListItems]
        
        this.btnLoading = false
      
    ,

【问题讨论】:

【参考方案1】:

我有点破解它,所以我不推荐它!

我用@choose 获得了所选项目,并在我的@end 中检查了我的数组的第一个索引是否是所选项目,unshift 数组并将所选项目添加到newIndexsplice(),如下所示:

setTimeout(() => 
  if(this.myItemsArray[this.oldIndex].id === this.choosedItem.id || this.myItemsArray[0].id === this.choosedItem.id)
    let arrayOfItems = [...this.originalItemsArray]
    arrayOfItems.shift()
    arrayOfItems.splice(this.newIndex,0,this.choosedItem)
    this.setCmsListItems(arrayOfItems)
    this.myItemsArray = [...this.cmsListItems]
    this.choosedItem = null
  
, 1);

【讨论】:

以上是关于vue项目中使用vuedraggable的主要内容,如果未能解决你的问题,请参考以下文章

vue拖拽排序插件vuedraggable的使用 附原生使用方法

vue基于vuedraggable实现拖拽

vue基于vuedraggable实现拖拽

vue+vuedraggable实现拖动排序和删除

带有 vuedraggable 的 Vue typescript 类组件

Sortable 的 VueDraggable 无法正常工作,并将所选项目发送到初始化时的第一个