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 // 支持拖拽排序
}
}