Vue组件设计之多列表拖拽交换排序功能实现

 更新时间:2023年05月05日 09:57:57   作者:aiguangyuan  
这篇文章主要介绍了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>

到此这篇关于Vue组件设计之多列表拖拽交换排序的文章就介绍到这了,更多相关vue拖拽交换排序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue开发常用方法详解

    Vue开发常用方法详解

    这篇文章主要为大家介绍了Vue开发常用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • vue mint-ui学习笔记之picker的使用

    vue mint-ui学习笔记之picker的使用

    本篇文章主要介绍了vue mint-ui学习笔记之picker的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • vue 通过 Prop 向子组件传递数据的实现方法

    vue 通过 Prop 向子组件传递数据的实现方法

    这篇文章主要介绍了vue 通过 Prop 向子组件传递数据的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • vuex结合session存储数据解决页面刷新数据丢失问题

    vuex结合session存储数据解决页面刷新数据丢失问题

    在项目中表单筛选项里,选择完之后刷新页面数据就变了,没有保留在自己选择的选项上。本文使用session存储数据,具有一定的参考价值,感兴趣的可以了解一下
    2021-09-09
  • vue.js使用v-if实现显示与隐藏功能示例

    vue.js使用v-if实现显示与隐藏功能示例

    这篇文章主要介绍了vue.js使用v-if实现显示与隐藏功能,结合简单实例形式分析了使用v-if进行判断实现元素的显示与隐藏功能,需要的朋友可以参考下
    2018-07-07
  • vue3单文件组件中style特性的深入讲解

    vue3单文件组件中style特性的深入讲解

    单文件就是把一个页面拆分为多个,多层次的组件,通过多层引用,大大缩小vue文件的长度和页面复杂度,下面这篇文章主要给大家介绍了关于vue3单文件组件中style特性的相关资料,需要的朋友可以参考下
    2021-09-09
  • vue实现输入框只允许输入数字

    vue实现输入框只允许输入数字

    在vue项目中,输入框只允许输入数字,现将自己使用的一种方法记录,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2023-11-11
  • Electron主进程(Main Process)与渲染进程(Renderer Process)通信详解

    Electron主进程(Main Process)与渲染进程(Renderer Process)通信详解

    这篇文章主要介绍了Electron主进程(Main Process)与渲染进程(Renderer Process)通信,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • vue cli 3.x 项目部署到 github pages的方法

    vue cli 3.x 项目部署到 github pages的方法

    这篇文章主要介绍了vue cli 3.x 项目部署到 github pages的方法,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下
    2019-04-04
  • vue中el-date-picker选择日期的限制的项目实践

    vue中el-date-picker选择日期的限制的项目实践

    ElementUI的el-date-picker使用时,有时候想要限制用户选择的时间范围,本文就来介绍了vue中el-date-picker选择日期的限制的项目实践,感兴趣的可以了解一下
    2023-10-10

最新评论