Vue组件设计之多列表拖拽交换排序功能实现
作者:aiguangyuan 发布时间:2024-04-27 15:49:28
标签:vue,拖拽,排序
在前端开发中,拖拽排序是一种提升用户体验非常好的方式,常见的场景有单列表拖拽排序,多列表拖拽交换排序,比如以下这种效果:
下面将以这种效果为例,设计一个组件。
1. 安装所需依赖
npm install vuedraggable --save
本例中目前所用的版本为:2.20.0
2. 组件设计实现
<template>
<div class="dnd-list">
<div class="dnd-list-aside" :style="{width:width1 }" >
<h3>{{ list1Title }}</h3>
<draggable :list="list1" group="article" class="drag-area" :set-data="setData">
<div :key="element.id" v-for="element in list1" class="list-complete-item">
<div class="list-complete-item-handle1">
{{ element.id }} {{ element.title }} [{{ element.author }}]
</div>
<div style="position:absolute;right:0px">
<span style="float:right;margin-top:-20px;margin-right:5px;" @click="deleteItem(element)">
<i style="color: #ff4949" class="el-icon-delete" />
</span>
</div>
</div>
</draggable>
</div>
<div class="dnd-list-aside" :style="{width:width2}">
<h3>{{ list2Title }}</h3>
<draggable :list="list2" group="article" class="drag-area">
<div :key="element.id" v-for="element in list2" class="list-complete-item">
<div class="list-complete-item-handle2" @click="pushItem(element)">
{{ element.id }} {{ element.title }} [{{ element.author }}]
</div>
</div>
</draggable>
</div>
</div>
</template>
<script>
import draggable from "vuedraggable";
export default {
name: "DndList",
components: { draggable },
props: {
list1: {
type: Array,
default() {
return [];
},
},
list2: {
type: Array,
default() {
return [];
},
},
list1Title: {
type: String,
default: "list1",
},
list2Title: {
type: String,
default: "list2",
},
width1: {
type: String,
default: "48%",
},
width2: {
type: String,
default: "48%",
},
},
methods: {
// 是否在列表一
isNotInList1(v) {
return this.list1.every((k) => v.id !== k.id);
},
// 是否在列表二
isNotInList2(v) {
return this.list2.every((k) => v.id !== k.id);
},
// 删除列表项
deleteItem(element) {
for (const item of this.list1) {
if (item.id === element.id) {
const index = this.list1.indexOf(item);
this.list1.splice(index, 1);
break;
}
}
if (this.isNotInList2(element)) {
this.list2.unshift(element);
}
},
// 点击切换列表项
pushItem(element) {
for (const item of this.list2) {
if (item.id === element.id) {
const index = this.list2.indexOf(item);
this.list2.splice(index, 1);
break;
}
}
if (this.isNotInList1(element)) {
this.list1.push(element);
}
},
// 拖拽交换时
setData(dataTransfer) {
// 解决火狐问题
// 详见 : https://github.com/RubaXa/Sortable/issues/1012
dataTransfer.setData("Text", "");
},
},
};
</script>
<style lang="scss" scoped>
.dnd-list {
background: #fff;
padding-bottom: 40px;
&:after {
content: "";
display: table;
clear: both;
}
.dnd-list-aside {
float:left;
padding-bottom: 30px;
&:first-of-type {
margin-right: 2%;
}
.drag-area{
margin-top: 15px;
min-height: 50px;
padding-bottom: 30px;
}
}
}
.list-complete-item {
cursor: pointer;
position: relative;
font-size: 14px;
padding: 5px 12px;
margin-top: 4px;
border: 1px solid #bfcbd9;
transition: all 1s;
}
.list-complete-item-handle1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 50px;
}
.list-complete-item-handle2 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 20px;
}
.list-complete-item.sortable-chosen {
background: #4ab7bd;
}
.list-complete-item.sortable-ghost {
background: #30b08f;
}
.list-complete-enter,.list-complete-leave-active {
opacity: 0;
}
</style>
3. 组件使用示例
<template>
<div class="box">
<DndList :list1="list1" :list2="list2" :list1Title="list1Title" :list2Title="list2Title"></DndList>
</div>
</template>
<script>
import DndList from "@/components/DndList";
export default {
components:{
DndList:DndList
},
data() {
return {
list1:[
{id:1,title:"《西游记》",author:"吴承恩"},
{id:2,title:"《红楼梦》",author:"曹雪芹"},
{id:3,title:"《水浒传》",author:"施耐庵"},
{id:4,title:"《三国演义》",author:"罗贯中"},
{id:5,title:"《名人传》",author:"罗曼罗兰"},
{id:6,title:"《钢铁是怎样炼成的》",author:"奥斯特洛夫斯基"},
],
list2:[
{id:7,title:"《鲁宾逊漂流记》",author:"笛福"},
{id:8,title:"《格列佛游记》",author:"约翰斯威夫特"},
{id:9,title:"《繁星春水》",author:"冰心"},
],
list1Title:"我的图书收藏",
list2Title:"已读完的图书"
};
}
}
</script>
<style scoped>
.box{
width:600px;
margin:20px;
padding:10px;
background:#fff;
}
</style>
来源:https://blog.csdn.net/weixin_40629244/article/details/130482372


猜你喜欢
- 下面是一段产生log-normal分布的代码,以此进行说明。clear all;clc;for t=1:100 Traffic(t) =cu
- onchange在用于文本框输入框时,有一个明显的不足. 事件不会随着文字的输入而触发,而是等到文本框失去焦点(onblur)时才会触发.
- 窗口标题pygame.display.set_caption(title, icontitle=None)'''•
- 1.冒泡排序,相邻位置比较大小,将比较大的(或小的)交换位置def maopao(a): for i in ran
- XML虽然比JSON复杂,在Web中应用也不如以前多了,不过仍有很多地方在用,所以,有必要了解如何操作XML。DOM vs SAX操作XML
- 自从看了蒋鑫的《Git权威指南》之后就开始使用Git Submodule功能,团队也都熟悉了怎么使用,多个子系统(模块)都能及时更新到最新的
- 很多朋友对FrontPage2003中增加的网页布局功能很感兴趣,现在我们一起来深入了解这一实用功能。 用FrontPage200
- JavaScript 中的 this 指向问题有很多文章在解释,仍然有很多人问。上周我们的开发团队连续两个人遇到相关问题,所以我不得不将关于
- 用Pdb调试有多种方式使用 Pdb调试 Python的程序的方式主要是下面的三种!下面逐一介绍命令行加-m参数命令行启动目标程序,加上-m参
- 1 PromisePromise有一个缺点是一旦创建无法取消,所以本质上Promise是无法被终止的.但是我们可以通过中断调用链或中断Pro
- 选中需要操作的字符Ctrl + R 替换Ctrl + Shift + F 全局查找Ctrl + Shift + R 全局替换来源:http:
- --1. 创建表,添加测试数据 CREATE TABLE tb(id int, [value] varchar(10)) INSERT tb
- 选择题以下python代码输出什么?a = [2,3,1]sorted(a)print(a)A aB [3, 2, 1]C [2, 3, 1
- 以下就重复记录删除的问题作一阐述。 有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如N
- 以下所有例子中结构定义如下:type User struct { Id_ bson.ObjectId `bson:
- >>什么是RPCRPC 的全称是 Remote Procedure Call 是一种进程间通信方式。它允许程序调用另一个地址空间
- 1. 是什么?MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Da
- Pytorch的backward()函数假若有多个loss函数,如何进行反向传播和更新呢? x = torch.tensor(2.0, re
- 版本:MySQL-5.7.32前言:对于业务繁忙的数据库来说,在运行了一定时间后,往往会产生一些数据量较大的表,特别是对于每天新增数据较多的
- <!DOCTYPE html><html lang="en"><head> <