<template>
<div class="title-list">
v-dragging="{item: item, list:list}"
v-for="item in list"
:key="item.id"
class="title-item">
<div class="title-child">
<span>{{item.id +"--"+ item.name }}</span>
</template>
<script>
export default {
name: "titleList",
data() {
return {
list: [
{id:1,name:"这是第一个标题名称"},
{id:2,name:"这是第二个标题名称"},
{id:3,name:"这是第三个标题名称"},
{id:4,name:"这是第四个标题名称"},
{id:5,name:"这是第五个标题名称"},
mounted() {
// 拖拽事件
this.$dragging.$on("dragged", (result) => {
// 将排序后的结果重新赋值
this.list = result.value.list;
</script>
<style lang="scss" scoped>
.title-list {
width: 350px;
background:#fff;
margin:100px auto 0;
border: 1px solid red;
.title-item {
width: 350px;
cursor: pointer;
border: 1px solid #ededed;
.title-child {
width: 330px;
height: 60px;
margin: 0 auto;
position: relative;
span {
width: 100%;
font-size: 14px;
color: red;
line-height: 30px;
// 只显示两行,多余的以省略号显示
white-space: normal;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
// 无论一行还是两行均居中显示
position: absolute;
left: 0;
top: 50%;
transform: translate(0, -50%);
</style>
v-dragging=“{ item: item, list: colors, group: ‘item’,otherData:‘whatever u want’, comb: ‘isComb’}”
list: 列表的遍历数据,
item: 是当前循环值 , 遍历后需要拖拽功能的元素
group: “unique key of dragable list”即拖拽列表的独特key值
// 拖拽事件
this.$dragging.$on("dragged", (result) => {
debugger // console.log('result===>',result)
// result 拖拽后的信息 将排序后console.log的结果重新赋值
this.list = result.value.list;
项目中-- 拖拽的效果 不理想
功能能够实现,但拖拽的效果不是很好,无法修改拖拽图层的透明度
vue-smooth-DnD
Vue Smooth DnD 是一个快速、轻量级的拖放、可排序的 Vue.js 库,封装了 smooth-dnd 库。
vue-smooth-DnD 文档 : https://github.com/kutlugsahin/vue-smooth-dnd
安装 smooth-dnd
yarn add vue-smooth-dnd -S
API: container
属性 类型 默认值 描述 :orientation string vertical 容器的方向,可以为 horizontal 或 vertical :behaviour string move 描述被拖动的元素被移动或复制到目标容器。 可以为 move (容器间相互移动) 或 copy(将元素复制到其他容器,但本容器内元素不变) 或 drop-zone(在容器间移动,但是容器内元素的顺序是固定的) 或 contain (只能在容器内移动。) :tag string, NodeDescription div 容器的元素标签,默认是 div ,可以是字符串如 tag=“table” 也可以是包含 value和 props 属性的对象 :tag=“{value: ‘table’, props: {class: ‘my-table’}}” :group-name string undefined 可拖动元素可以在具有相同组名的容器之间移动。如果未设置组名容器将不接受来自外部的元素。 这种行为可以被 shouldAcceptDrop 函数覆盖。 :lock-axis string undefined 锁定拖动的移动轴。可用值 x, y 或 undefined。 :drag-handle-selector string undefined 用于指定可以开启拖拽的 CSS 选择器,如果不指定的话则元素内部任意位置都可抓取。 例如 drag-handle-selector=“.column-drag-handle” :non-drag-area-selector string undefined 禁止拖动的 CSS 选择器,优先于 dragHandleSelector. :drag-begin-delay number 0(触控设备为 200) 单位毫秒。表示点击元素持续多久后可以开始拖动。在此之前移动光标超过 5px 将取消拖动。 :animation-duration number 250 单位毫秒。表示放置元素和重新排序的动画持续时间。 :auto-scroll-enabled boolean true 如果拖动项目接近边界,第一个可滚动父项将自动滚动 :drag-class string undefined 元素被拖动中的添加的类(不会影响拖拽结束后元素的显示) :drop-class string undefined 从拖拽元素被放置到被添加到页面过程中添加的类。 :remove-on-drop-out boolean undefined 如果设置为 true,在被拖拽元素没有被放置到任何相关容器时,使用元素索引作为 removedIndex 调用 onDrop() :drop-placeholder boolean,object undefined 占位符的选项。包含 className, animationDuration, showOnTop 例如 dropPlaceholderOptions: { className: “drop-preview”, animationDuration: “150”, showOnTop: true, },
Container 属性的使用
<Container
group-name="col"
@drop="(e) => onCardDrop(column.id, e)"
:get-child-payload="getCardPayload(column.id)"
drag-class="card-ghost"
drop-class="card-ghost-drop"
:drop-placeholder="dropPlaceholderOptions"
class="draggable-container"
<Draggable v-for="task in column.list" :key="task.id">
<div class="task-card">
<div class="task-title">{{ task.name }}</div>
class="task-priority"
:style="{ background: priorityMap[task.priority].color }"
{{ priorityMap[task.priority].label }}
</Draggable>
</Container>
data() {
/// 拖拽时占位符样式
dropPlaceholderOptions: {
className: "drop-preview",
animationDuration: "150",
showOnTop: true,
smooth-dnd 生命周期
一次拖动的生命周期通过一系列回调和事件进行描述和控制,下面以包含 3 个容器的示例为例进行说明
Mouse Calls Callback / Event Parameters Notes
down o Initial click
move o Initial drag | | get-child-payload() index Function should return payload // 自定义传给 onDrop() 的payload对象。 | | 3 x should-accept-drop() srcOptions, payload Fired for all containers // 用来确定容器是否可被放置,会覆盖group-name属性。 | | 3 x drag-start dragResult Fired for all containers | | drag-enter v
move o Drag over containers | | n x drag-leave Fired as draggable leaves container | n x drag-enter Fired as draggable enters container v
up o Finish drag
should-animate-drop() srcOptions, payload Fires once for dropped container // 返回 false 则阻止放置动画
3 x drag-end dragResult Fired for all containers
n x drop dropResult Fired only for droppable containers
在每次拖动开始 (drag-start) 之前和每次拖动结束 (drag-end)之前触发should-accept-drop。
dragResult 参数配置 来源于 事件对象
(在事件处理函数中,可以传递一个参数e,这个参数我们叫做事件对象,也叫事件参数。事件对象e是系统传递过去,事件函数也是系统调用的。系统调用事件函数的时候,会给事件函数传递一个参数,传递的参数具有具体值,可以在事件函数执行时获取e中携带的值。)
drag-start 中的 dragResult 参数格式
dragResult: {
payload, // 负载 可以理解为用来记录被拖动的对象
isSource, // 是否是被拖动的容器本身
willAcceptDrop, // 是否可以被放置
drag-end 中的 dragResult 参数格式
dragResult: {
addedIndex, // 被放置的新添加元素的下标,没有则为 null
removedIndex, // 将被移除的元素下标,没有则为 null
payload, // 拖动的元素对象,可通过 getChildPayload 指定
droppedElement, // 放置的 DOM 元素
回调在用户交互之前和期间提供了额外的逻辑和检查。
自定义传给 onDrop() 的 payload 对象。
<Container :get-child-payload="getChildPayload">
getChildPayload (index) {
return {
// generate custom payload data here
should-accept-drop(sourceContainerOptions, payload)
在开始拖放之前,所有容器都要调用的函数用来确定容器是否可被放置,会覆盖 group-name 属性。
<Container :should-accept-drop="shouldAcceptDrop">
shouldAcceptDrop (sourceContainerOptions, payload) {
return true;
should-animate-drop(sourceContainerOptions, payload) 返回 false 则阻止放置动画。
<Container :should-animate-drop="shouldAnimateDrop">
shouldAnimateDrop (sourceContainerOptions, payload) {
return false;
get-ghost-parent() 返回幽灵元素(拖动时显示的元素)应该添加到的元素,默认是父元素,某些情况定位会出现问题,则可以选择自定义,如返回 document.body。
<Container :get-ghost-parent="getGhostParent">
getGhostParent() {
// i.e return document.body;
@drag-start 在拖动开始时由所有容器发出的事件。参数 dragResult。
<Container @drag-start="onDragStart">
onDragStart (dragResult) {
const { isSource, payload, willAcceptDrop } = dragResult
@drag-end 所有容器在拖动结束时调用的函数。 在 @drop 事件之前调用。参数 dragResult。 @drag-enter 每当拖动的项目在拖动时进入其边界时,相关容器要发出的事件。 @drag-leave 每当拖动的项目在拖动时离开其边界时,相关容器要发出的事件。 @drop-ready 当容器中可能放置位置的索引发生变化时,被拖动的容器将调用的函数。基本上,每次容器中的可拖动对象滑动以打开拖动项目的空间时都会调用它。参数 dropResult。 @drop 放置结束时所有相关容器会发出的事件(放置动画结束后)。源容器和任何可以接受放置的容器都被认为是相关的。参数 dropResult。
API: Draggable
Draggable 容器子组件的包装器。每个子元素都应该用可拖动组件包装。
同容器的 tag 指定可拖拽元素的 DOM 元素标签。 标记名称或节点定义来呈现Draggable的根元素。默认值为’div’。
<Draggable v-for="column in taskColumnList" :key="column.name" :tag="{value: 'tr', props: {class: 'my-table-row'}}">
</Draggable>
// --------------或者-----------------
<Draggable v-for="column in taskColumnList" :key="column.name" tag="tr">
</Draggable>
Vue Smooth DnD 主要包含了两个组件,Container 和 Draggable,Container 包含可拖动的元素或组件,它的每一个子元素都应该被 Draggable 包裹。
每一个要被设置为可拖动的元素都需要被 Draggable 包裹
<template>
<div class="simple-page">
<Container @drop="onDrop">
<Draggable v-for="item in items" :key="item.id">
<div class="draggable-item">
{{ item.data }}
</Draggable>
</Container>
</template>
<script>
import { Container, Draggable } from "vue-smooth-dnd";
const applyDrag = (arr, dragResult) => {
const { removedIndex, addedIndex, payload } = dragResult;
console.log(removedIndex, addedIndex, payload);
if (removedIndex === null && addedIndex === null) return arr;
const result = [...arr];
let itemToAdd = payload;
if (removedIndex !== null) {
itemToAdd = result.splice(removedIndex, 1)[0];
if (addedIndex !== null) {
result.splice(addedIndex, 0, itemToAdd);
return result;
const generateItems = (count, creator) => {
const result = [];
for (let i = 0; i < count; i++) {
result.push(creator(i));
return result;
export default {
name: "Simple",
components: { Container, Draggable },
data() {
return {
items: generateItems(50, (i) => ({ id: i, data: "Draggable " + i })),
methods: {
onDrop(dropResult) {
this.items = applyDrag(this.items, dropResult);
</script>
<style>
.draggable-item {
height: 50px;
line-height: 50px;
text-align: center;
display: block;
background-color: #fff;
outline: 0;
border: 1px solid rgba(0, 0, 0, 0.125);
margin-bottom: 2px;
margin-top: 2px;
cursor: default;
user-select: none;
</style>
项目中实现 – 拖拽位置无法确定
smooth 的 :orientation 属性限制了容器拖拽的方式,占位为一行默认为 vertical ,默认占位容器的一行
vuedraggable
import draggable from 'vuedraggable'
<template>
<div class="app-container">
<div :class="canEdit? 'dargBtn-lock el-icon-unlock': 'dargBtn-lock el-icon-lock' " @click="removeEvent()">{{canEdit? '调整':'锁定'}}</div>
<ul class="projset-content">
<draggable
:forceFallback="true"
:move="onMove"
:list="imgList"
handle=".dargBtn"
:animation="1000"
filter=".undraggable"
fallbackClass="fallbackStyle"
ghostClass="item_ghost"
chosenClass="chosenStyle"
dragClass="dragStyle"
<li v-for="(item, index) in imgList" :key="index" :class="canEdit ? 'draggable' : 'undraggable'">
<div class="dargBtn">
<svg-icon icon-class="drag" />
<img :src="item.path" alt="">
<span>{{item.name}}</span>
</draggable>
</template>
<script>
import draggable from 'vuedraggable';
export default {
components: { draggable},
data(){
return{
canEdit:true,
imgList: [
path: 'https://lupic.cdn.bcebos.com/20210629/3000005161_14.jpg',
name: '1',
path: 'https://lupic.cdn.bcebos.com/20210629/26202931_14.jpg',
name: '2',
path: 'https://lupic.cdn.bcebos.com/20210629/27788166_14.jpg',
name: '3',
created() {
mounted(){},
methods:{
onMove(relatedContext, draggedContext){
console.log(relatedContext.relatedContext.list);
removeEvent (item) {
if(this.canEdit){
this.canEdit = false;
}else{
this.canEdit = true;
console.log(this.canEdit);
</script>
<style scoped lang="scss">
.app-container{
background: #ffffff;
height: 100%;
.dargBtn-lock{
margin: 0px 50px;
color: #2ea9df;
.dragStyle {
padding: 10px;
border-radius: 4px;
opacity: 1;
.fallbackStyle{
padding: 10px;
border-radius: 4px;
opacity: 1;
.chosenStyle {
padding: 10px;
border-radius: 4px;
opacity: 1 !important;
.item_ghost {
opacity: 0 !important;
.projset-content{
list-style-type: none;
position: relative;
display: inline-block;
margin: 10px;
width: 141px;
height: 100px;
span{
justify-content: center;
display: flex;
.dargBtn{
position: absolute;
line-height: 100px;
text-align: center;
width: 141px;
height: 100px;
display: none;
color: white;
// background: rgba(101, 101, 101, 0.6);
.draggable{
cursor: pointer;
width: 141px;
height: 100px;
.draggable:hover .dargBtn{
display: block;
</style>
参数 类型 说明 group String/ Array group=“name” 用于分组, 同一组的不同list可以相互拖动 list Array 设置拖拽元素 sort Boolean :sort=“true” 是否开启内部排序, 如果设为 false 则它所在的组无法排序 delay Number :delay=“0” 鼠标选中后可以开始拖拽的延迟时间 touchStartThreshold Number :touchStartThreshold=“5” 鼠标移动多少px才可以拖动元素 disabled Boolean :disabled=“true” 是否启用拖拽组件 animation Number :animation="1000"单位 ms 拖动时过渡动画效果 handle Selector handle=“.card-title” 拖动手柄,鼠标移动到 css 名为 card-title 的选择器时才能成为拖动手柄进行拖动 filter Selector filter=“.unmover” 通过选择器设置哪些样式的元素不能被拖动 多个选择器用 ‘,’ 分隔 preventOnFilter Boolean :preventOnFilter="true"默认触发 当拖动filter时是否触发 event.preventDefault() draggable Selector draggable=“.item” 哪些元素时可以进行拖动的 ghostClass ghostClass=“ghost-style” 设置拖拽元素的占位符样式 模拟被拖动元素的排序情况,自定义样式可能需要添加 !important 才能生效(forceFallback 属性设置味 true) chosenClass chosenClass=“chosen-style” 设置目标被选中时的样式(包括拖拽时鼠标附着的样式)自定义样式可能需要添加 !important 才能生效(forceFallback 属性设置味 true) dragClass dragClass=“drag-style” 拖动元素过程中添加的样式,自定义样式可能需要添加 !important 才能生效(forceFallback 属性设置味 true) dataIdAttr Selector dataIdAttr=”data-id“ 不太清楚 forceFallback forceFallback=“true” 默认为false 设为 true 时将不使用原生的html5 的拖放,可修改拖放过程中的样式 fallbackClass fallback-class=“dragging_style” forceFallback=“true” 时,克隆出新的DOM元素类名,可修改拖放过程中鼠标附着的样式 allbackOnBody Boolean 默认为false allbackOnBody=“true” 时将克隆的元素添加到文档的body中 fallbackTolerance Number 单位 px 拖拽之前应该移动的距离 scroll Boolean 默认为true 当排序的容器是个可滚动的区域,拖放是否能引起区域滚动 scrollFn Function 滚动回调函数,用于自定义滚动条的适配 scrollSensitivity Number 默认30 距离滚动区域多远时滚动条滚动,鼠标靠近边缘多远时开始滚动 scorllSpeed Number 滚动速度
参数 说明 回调参数 start 开始拖动时 function({ to, from, item, clone, oldIndex, newIndex }) add 往列表中移入(添加)单元时 function({ to, from, item, clone, oldIndex, newIndex }) remove 单元被移动到另一个列表(从当前的列表移处)时 function({ to, from, item, clone, oldIndex, newIndex }) update 排序发生变化时 function({ to, from, item, clone, oldIndex, newIndex }) end 拖拽结束时 function({ to, from, item, clone, oldIndex, newIndex }) choose 选择单元格时 function({ to, from, item, clone, oldIndex, newIndex }) sort 排序发生变化时 function({ to, from, item, clone, oldIndex, newIndex }) filter 尝试选择一个被filter过滤的单元时 function({ to, from, item, clone, oldIndex, newIndex }) clone clone 复制出单元格时触发 function({ to, from, item, clone, oldIndex, newIndex })
<transition>
<draggable
:delay="300"
:fallback-tolerance="0"
:list="dragList"
:force-fallback="true"
fallback-class="dragging_style"
handle=".card-title"
drag-class="drag-style"
ghost-class="ghost-style"
chosen-class="chosen-style"
@update="handleUpdateDrag"
class="home-drag-wrapper">
<div v-for=" item in dragList" :key="item.id" :class="item.className" class="home-part">
<component :is="item.name" :ref="item.name" class="drag-handle " :class=" item.id !== 1? (item.id !== 2? 'card': ''):''"> </component>
</draggable>
</transition>
.ghost-style {
opacity: 0;
cursor: grabbing !important;
.chosen-style {
background-color: rgba(242, 245, 250, .5);
border-radius: 8px;
z-index: 1000;
box-shadow: 0px 3px 28px #BAC4D4;
cursor: grabbing !important;
.dragging-style {
border: 1px solid yellow;
.drag-style {
background-color: rgba(242, 245, 250, .5);
border-radius: 8px;
z-index: 1000;
box-shadow: 0px 3px 28px #BAC4D4;
opacity: 1 !important;
ghost-class 为排序中的占位样式。
chosen-class 占位符、拖动过程中鼠标附着的副本样式的共同样式。
设置 :force-fallback=“true” 可修改拖放过程中的样式
fallback-class 设置鼠标附着的副本样式, 通过 !important 提升样式优先级。
drag-class 拖拽过程中的样式(鼠标附着样式 opacity: 1 !important; 设置副本的透明度)。
在拖拽过程中配置的类名作用的相应区域:
通过试用多个不同的组件库,恍惚比较总结,最后在项目重采用vuedraggable,因为该组件的实现方式简单,并且能够灵活控制拖拽的样式,达到所需的效果。
到此这篇关于vue中实现拖拽排序功能的文章就介绍到这了,更多相关vue实现拖拽排序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
smooth- dnd 参考自 : https://blog.51cto.com/u_15127632/4038149
vuedraggable 参考自:https://blog.csdn.net/Kiruthika/article/details/123903706
您可能感兴趣的文章:
mint-ui如何自定义messageBox样式 2023-05-05
Vue中引入json的三种方式总结 2023-05-05
vue使用moment如何将时间戳转为标准日期时间格式 2023-05-05
深入了解Vue.js中的Vuex状态管理模式 2023-05-05
vue中如何实现拖拽调整顺序功能 2023-05-05
Vue项目打包到服务器后请求接口报错404的解决 2023-05-05
Vue使用mockjs问题(返回数据、get、post 请求) 2023-05-05
在vue中如何使用Mock.js模拟数据 2023-05-05
美国设下计谋,用娘炮文化重塑日本,已影响至中国 2021-11-19 时空伴随者是什么意思?时空伴随者介绍 2021-11-09 工信部称网盘企业免费用户最低速率应满足基本下载需求,天翼云盘回应:坚决支持,始终 2021-11-05 2022年放假安排出炉:五一连休5天 2022年所有节日一览表 2021-10-26
电脑版 - 返回首页
2006-2023 脚本之家 JB51.Net , All Rights Reserved. 苏ICP备14036222号