vue项目通过vuedraggable拖拽功能

1,578 阅读3分钟

vue项目可以通过vuedraggable插件实现拖拽功能。
vuedraggable中文文档
可以通过npm下载安装插件:

npm install --save vuedraggable

在项目中需要实现的效果是,左边的内容组件拖拽到中间显示区域显示,左边内容不支持拖拽排序,中间显示区域支持拖拽排序显示,但不支持拖拽回左边的内容框,如下图所示:
下面看一下我在项目中的使用代码:
phone.vue-----拖拽进来显示的内容区域文件:

<!--两列组件设置相同的group名就可以相互拖拽了-->
<!--draggable绑定的数组必须是和里面的for循环是同一个数组-->
<draggable
  :value="dataList"
  group="h5template"
  :disableDrag="disableDrag"
  :dragOptions="dragOptions"
  chosenClass="chosen"
  forceFallback="true"
  @change="dragChange"
  style="width: 100%; min-height: 100%;"
>
  <transition-group
    style="display: inline-block; width: 100%;"
    :style="isReadable ? '' : 'min-height: 480px;'"
  >
  	<!--里面的第一个盒子必须是for循环-->
	<div v-for="(item, index) in dataList" :key="index">
         {{item}}
  	</div>
   </transition-group>
</draggable>

import draggable from 'vuedraggable'
import { abledDragOptions } from "@/mixins/dragOptions"; //拖拽滚动配置
import { options } from "@/mixins/BScrollOptions"; //拖拽滚动配置

data() {
  return {
    disableDrag: true, // 允许拖拽
    dragOptions: abledDragOptions, // 拖拽的配置
  }
},

// 排序改变事件
dragChange(evt) {
  // 当拖拽内容进来会走这个方法,当内容数组排序发生变化之后也会走进这个方法  
  // 这里是拖拽进来之后或者排序发送变化之后的一些操作
  // 我这里是从vuex里获取数据出来显示的,只要是拖拽进来了就显示,如果是拖拽改变内容数组的排序就更新vuex里的内容数组
  if (evt.moved) {
    //内容数组排序发生变化走这里,这里更新vuex里的内容数组数据
  } else if (evt.added) {
    // 拖拽内容进入显示区域走这里,这里就push数据到vuex里的内容数组,显示被拖拽的内容
  }
},

phone.vue内容显示区域拖拽排序,可以上移或者下移,注意看逻辑,下标index不要搞错,需要做的操作:

// 模块内容列表顺序发生改变,注意看逻辑,下标index不要搞错
dragChange(evt) {
  if (evt.moved) {
    const newIndex = evt.moved.newIndex; // 拖拽之后的index
    const oldIndex = evt.moved.oldIndex; // 拖拽之前的index
    let data = JSON.parse(JSON.stringify(H5templateModule.dataList));
    const dataList = data.filter(item => item.type != 5);
    if (newIndex > oldIndex) { // 往下移动,先插入新位置的item再删除原来位置上的item
      dataList.splice(newIndex+1, 0, dataList[oldIndex]);
      dataList.splice(oldIndex, 1);
    } else { // 往上移动,
      dataList.splice(newIndex, 0, dataList[oldIndex]);
      dataList.splice(oldIndex+1, 1);
    }
    H5templateModule.updateDataList(dataList);
  } else if (evt.added) {
    // 拖拽元素被移动进来了,通过vuex来获取,通过setTimeout获取vuex的数据
    let time = setTimeout(() => {
      const newIndex = evt.added.newIndex; // 拖拽之后的index
      let dataList = JSON.parse(JSON.stringify(H5templateModule.dataList));
      dataList.splice(newIndex, 0, this.getAddItem); // 插入被拖拽的item
      H5templateModule.updateDataList(dataList);
    });
  }
},

dragContent.vue-----被拖拽的内容文件

<!--两列组件设置相同的group名就可以相互拖拽了-->
<!--draggable绑定的数组必须是和里面的for循环是同一个数组-->
<draggable
  class="dragBox"
  v-model="titles"
  v-bind="dragOptions"
  :disableDrag="disableDrag"
  chosenClass="chosen"
  @end="onEnd"
>
  <transition-group>
  	<!--里面的第一个盒子必须是for循环-->
    <div class="item" v-for="(item, index) in titles" :key="index">
      {{item.label}}
    </div>
  </transition-group>
</draggable>

import draggable from 'vuedraggable'
import { dragOptions } from "@/mixins/dragOptions"; //拖拽滚动配置

data() {
  return {
     titles: [
      {
        id: "0",
        label: "主标题",
      },
      {
        id: "1",
        label: "次标题",
      },
      {
        id: "2",
        label: "正文",
      },
      {
        id: "3",
        label: "说明文字",
      },
    ],
    disableDrag: true, // 允许拖拽
    dragOptions, // 拖拽的配置
  }
},

//拖拽结束事件
onEnd(evt) {
  console.log(evt);
  const oldIndex = evt.oldIndex; // 拖拽之前的index
  const currentItem = this.titles[oldIndex]; // 获取到被拖拽的item
  H5templateModule.updateAddItem(currentItem); // 保存到vuex里
  // 这里拖拽结束后走进这个方法,可以写一下拖拽之后需要做的操作我是通过拖拽之后保存到vuex里,在phone.vue文件里获取vuex的数据显示内容的,
},

根据打印出来的拖拽结束事件可以得到拖拽之前和拖拽之后的index和内容数组列表,以及拖拽之前DOM节点和拖拽之后的className;
mixins.js-----配置拖拽options的文件:

// 拖拽的配置(不支持拖拽排序)
export const dragOptions = {
  sort: false, // 拖拽时禁止排序操作
  animation: 300,
  forceFallback: true, // 不使用原生的html5的拖放
  ghostClass: 'ghostClass',
  dragClass: 'dragClass',
  group: {
    name: 'h5template',
    pull:'clone', // 进行克隆拖拽操作, 这样配置之后,会保留被拖拽的项
    put: false, // 不支持拖拽排序
  }
}

// 支持拖拽排序
export const abledDragOptions = {
  sort: false, // 拖拽时禁止排序操作
  animation: 300,
  forceFallback: true, // 不使用原生的html5的拖放
  ghostClass: 'ghostClass',
  dragClass: 'dragClass',
  group: {
    name: 'h5template',
    pull:'clone', // 进行克隆拖拽操作, 这样配置之后,会保留被拖拽的项
    put: true // 支持拖拽排序
  }
}