Vue使用vue-draggable 插件在不同列表之间拖拽功能


Posted in Javascript onMarch 12, 2020

今天分享一个vue项目中在不同列表拖拽设置选项的功能,这个功能也是在做项目中遇到的,先说下这个功能的要点(参考下图),有2个列表,左侧列表展示已选,右侧列表展示未选,通过拖拽进行设置,已选的选项不能超过4个,超过的话自动将拖拽之前的最后一项清除到右侧,且如果从已选往未选里拖的时候,右侧显示垃圾桶的提示(如图)。

拖拽功能图片:

Vue使用vue-draggable 插件在不同列表之间拖拽功能

垃圾桶显示图:

Vue使用vue-draggable 插件在不同列表之间拖拽功能

首先讲讲vue-draggable的使用

安装vue-draggable:

npm install vuedraggable

在使用插件的组件内引入vue-draggable并注册组件:

import draggable from "vuedraggable"

components: {
 draggable
}

然后在我们需要拖拽的列表中使用:

<draggable class="selected-list" tag="ul" 
v-model="selectedTheme" 
v-bind="dragOptions"
 :move="onMove"
 @end="onEnd" 
 >
 <li class="selected-theme"
 v-for="item in selectedTheme"
 :key="item.type"
 >{{item.name}}</li>
</draggable>

下面是拖拽功能组件的完整代码:

<template>
 <div class="theme-setting">
 <el-dialog
 title="设置选项"
 :visible.sync="dialogVisible"
 width="648px"
 :close-on-click-modal="false"
 >
 <div class="theme-left">
  <dl class="theme-title">
  <dt class="title">当前选项</dt>
  <dd class="des">从右侧拖拽添加</dd>
  </dl>
  <draggable class="selected-list" tag="ul" 
  v-model="selectedTheme" 
  v-bind="dragOptions"
  :move="onMove"
  @end="onEnd" 
  >
  <li class="selected-theme"
  v-for="item in selectedTheme"
  :key="item.type"
  >{{item.name}}</li>
  </draggable>
 </div>
 <div class="theme-right">
  <h3 class="theme-right-title">全部选项</h3>
  <draggable class="theme-right-list" tag="ul"
  v-model="unSelectTheme"
  v-bind="dragOptions"
  :move="onMove"
  @end="onEnd">
  <li class="theme-right-item"
  v-for="item in unSelectTheme"
  :key="item.type"
  >{{item.name}}</li>
  </draggable>
 </div>
 <div class="drag-drop-del" v-show="isShowDel">
  <img src="../assets/imgs/drapDrop/drag_drop_del.png" alt="">
 </div>
 <span slot="footer" class="dialog-footer">
  <el-button @click="restoreDefault">恢复默认设置</el-button>
  <el-button type="primary" @click="saveThemeSet">保存</el-button>
 </span>
 </el-dialog>
 </div>
</template>

<script>
import {Message} from 'element-ui'
import draggable from "vuedraggable" 
 export default {
 name: 'DragDrop',
 components: {
 draggable
 },
 data() {
 return {
  dialogVisible: false,
  selectedTheme: [{
  type: 1,
  name: '选项1'
  }, {
  type: 2,
  name: '选项2'
  }, {
  type: 3,
  name: '选项3'
  }, {
  type: 4,
  name: '选项4'
  }], // 已选主题列表
  unSelectTheme: [{
  type: 5,
  name: '选项5'
  }, {
  type: 6,
  name: '选项6'
  }], // 未选主题列表
  backSelectedTheme: [], // 选主题列表备份
  backUnSelectTheme: [], // 未选主题列表备份用于恢复默认设置
  relatedListLast: {}, // 已选主题列表最后一项
  isShowDel: false
 }
 },
 methods: {
 showDrag() {
  this.dialogVisible = true
 },
 onMove({ relatedContext, draggedContext, to }) {
  const relatedElement = relatedContext.element
  const draggedElement = draggedContext.element
  let dragInEl = to['className']
  if (dragInEl == 'selected-list') {
  this.isShowDel = false
  if (this.selectedTheme.length === 4) { 
   // 判断往已选列表拖时,如果已经满足4项,则记录已选列表的最后一项
   // 拖拽结束时将此项清除到未选列表中
   this.relatedListLast = this.selectedTheme[this.selectedTheme.length-1]
  }
  } else {
  this.isShowDel = true // 判断如果是往未选列表里拖的话显示垃圾桶
  }
  return (
  (!relatedElement || !relatedElement.fixed) && !draggedElement.fixed
  )
 },
 onEnd(dragObj) {
  let dragInEl = dragObj.to['className']
  if (dragInEl == 'selected-list') {
  if (this.selectedTheme.length > 4) {
   // 判断已选列表大于4项,将记录的最后一项过滤出来,并push到未选列表数组
   this.selectedTheme = this.selectedTheme.filter(item => {
   return item.type != this.relatedListLast.type
   })
   this.unSelectTheme.push(this.relatedListLast)
  }
  }
  if (dragInEl === 'theme-right-list') {
  // 判断是往未选列表拖时,拖拽结束时将垃圾桶隐藏
  this.isShowDel = false
  }
 },
 // 保存设置
 saveThemeSet() {
  const params = {
  taskTopicList: this.selectedTheme
  }
  if (this.selectedTheme.length !== 4) {
  Message({
   type: 'error',
   message: '需设置4个选项 !'
  })
  return false
  }
  $ajax.save(params).then(data => {
  this.dialogVisible = false
  Message({
   type: 'success',
   message: '保存成功!'
  })
  this.$parent.refresh()
  }).catch(err => {
  console.log(err)
  })
 },
 // 恢复默认设置
 restoreDefault() {
  this.selectedTheme = this.backSelectedTheme
  this.unSelectTheme = this.backUnSelectTheme
 }
 },
 computed: {
 dragOptions() {
  return {
  animation: 0,
  group: "description",
  disabled: false,
  ghostClass: "ghost"
  }
 }
 }
 };
</script>
<style lang="less" scoped>
body, ul, dl, dt, dd, li, h1, h3{
 margin: 0;
 padding: 0;
}
ul, ol, li {
 list-style: none;
}
.theme-setting {
 /deep/.el-dialog {
 height: 476px;
 border-radius: 6px;
 .el-dialog__header {
  height: 55px;
  line-height: 56px;
  padding: 0;
  border-bottom: 1px solid rgba(13,20,30, 0.1);
  .el-dialog__title {
  height:21px;
  font-size:16px;
  font-family:MicrosoftYaHei-Bold,MicrosoftYaHei;
  font-weight:bold;
  color:rgba(13,20,30,1);
  line-height:21px;
  }
  .el-dialog__headerbtn {
  margin-top: -4px;
  }
 }
 .el-dialog__body {
  position: relative;
  display: flex;
  height: 331px;
  padding: 0;
  border-bottom: 1px solid rgba(13,20,30, 0.1);
  .theme-left {
  width: 218px;
  margin-left: 24px;
  border-right: 1px solid rgba(13,20,30, 0.1);
  .theme-title {
   display: flex;
   margin-top: 24px;
   .title {
   height:19px;
   margin-right: 4px;
   font-size:14px;
   font-family:MicrosoftYaHei-Bold,MicrosoftYaHei;
   font-weight:bold;
   color:rgba(13,20,30,1);
   line-height:19px;
   }
   .des {
   height:16px;
   font-size:12px;
   font-family:MicrosoftYaHei;
   color:rgba(13,20,30,0.6);
   line-height:19px;
   }
  }
  .selected-list {
   height: 240px;
   margin-top: 24px;
   overflow: hidden;
   .selected-theme {
   width:160px;
   height:48px;
   line-height:48px;
   text-align: center;
   margin-bottom: 16px;
   cursor: pointer;
   background:linear-gradient(180deg,rgba(43,46,83,1) 0%,rgba(108,116,150,1) 100%);
   border-radius:6px;
   font-size:14px;
   font-family:MicrosoftYaHei;
   color:rgba(255,255,255,1);
   }
  }
  }
  .theme-right {
  padding: 0 24px;
  .theme-right-title {
   padding-top: 24px;
   height:19px;
   font-size:14px;
   font-family:MicrosoftYaHei-Bold,MicrosoftYaHei;
   font-weight:bold;
   color:rgba(13,20,30,0.4);
   line-height:19px;
  }
  .theme-right-list {
   width: 357px;
   height: 240px;
   overflow: scroll;
   margin-top: 24px;
   .theme-right-item {
   width: 160px;
   height:48px;
   line-height:48px;
   float: left;
   margin-right: 16px;
   margin-bottom: 16px;
   background:rgba(247,248,252,1);
   border-radius:6px;
   font-size:14px;
   font-family:MicrosoftYaHei;
   color:rgba(13,20,30,0.4);
   text-align: center;
   cursor: pointer;
   }
  }
  .theme-right-list::before, .theme-right-list::after {
   content: "";
   display: table;
  }
  .theme-right-list::after {
   clear: both;
  }
  }
  .drag-drop-del {
  position: absolute;
  right: 1px;
  top: 0;
  width: 404px;
  height: 331px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-image: url('../../src/assets/imgs/drapDrop/drag_drop.png');
  img {
   width: 96px;
   height: 96px;
  }
  }
 }
 .el-dialog__footer {
  height: 88px;
  padding: 24px 24px 0;
  .dialog-footer {
  .el-button+.el-button {
   margin-left: 16px;
  }
  }
 }
 }
}
</style>

总结

到此这篇关于Vue使用vue-draggable 插件在不同列表之间拖拽功能的文章就介绍到这了,更多相关vue vue-draggable 插件 拖拽内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
JavaScript null和undefined区别分析
Oct 14 Javascript
Javascript 面向对象(二)封装代码
May 23 Javascript
js怎么终止程序return不行换jfslk
May 30 Javascript
jquery调取json数据实现省市级联的方法
Jan 29 Javascript
详解javascript高级定时器
Dec 31 Javascript
jQuery实现定位滚动条位置
Aug 05 Javascript
JavaScript队列函数和异步执行详解
Jun 19 Javascript
深入理解Vue-cli搭建项目后的目录结构探秘
Jul 13 Javascript
Javascript(es2016) import和require用法和区别详解
Aug 11 Javascript
vue.js移动数组位置,同时更新视图的方法
Mar 08 Javascript
jquery实现选项卡切换代码实例
May 14 jQuery
JavaScript实现背景自动切换小案例
Sep 27 Javascript
js实现动态时钟
Mar 12 #Javascript
package.json各个属性说明详解
Mar 11 #Javascript
package.json中homepage属性的作用详解
Mar 11 #Javascript
vue项目中使用vue-layer弹框插件的方法
Mar 11 #Javascript
Vue组件模板及组件互相引用代码实例
Mar 11 #Javascript
Vue组件间的通信pubsub-js实现步骤解析
Mar 11 #Javascript
Vue事件处理原理及过程详解
Mar 11 #Javascript
You might like
php解析url的三个示例
2014/01/20 PHP
php框架知识点的整理和补充
2021/03/01 PHP
Mozilla中显示textarea中选择的文字
2006/09/07 Javascript
实现png图片和png背景透明(支持多浏览器)的方法
2009/09/08 Javascript
jQuery模拟黑客帝国矩阵效果实例
2015/06/28 Javascript
JS基于clipBoard.js插件实现剪切、复制、粘贴
2016/05/03 Javascript
JS实现禁止鼠标右键的功能
2016/10/15 Javascript
vue.js学习笔记之绑定style样式和class列表
2016/10/31 Javascript
vue-router跳转页面的方法
2017/02/09 Javascript
JavaScript 上传文件(psd,压缩包等),图片,视频的实现方法
2017/06/19 Javascript
详解Vue.js Mixins 混入使用
2017/09/15 Javascript
JavaScript判断输入是否为数字类型的方法总结
2017/09/28 Javascript
JavaScript获取用户所在城市及地理位置
2018/04/21 Javascript
vue展示dicom文件医疗系统的实现代码
2018/08/27 Javascript
swiper实现导航滚动效果
2020/12/13 Javascript
Python THREADING模块中的JOIN()方法深入理解
2015/02/18 Python
Python构造函数及解构函数介绍
2015/02/26 Python
python实现图片文件批量重命名
2020/03/23 Python
使用python将大量数据导出到Excel中的小技巧分享
2018/06/14 Python
Django2.1.3 中间件使用详解
2018/11/26 Python
使用pandas实现csv/excel sheet互相转换的方法
2018/12/10 Python
python中的反斜杠问题深入讲解
2019/08/12 Python
Pytorch.nn.conv2d 过程验证方式(单,多通道卷积过程)
2020/01/03 Python
dpn网络的pytorch实现方式
2020/01/14 Python
Tensorflow 卷积的梯度反向传播过程
2020/02/10 Python
python读取excel数据并且画图的实现示例
2021/02/08 Python
师范生的个人求职信范文
2014/01/04 职场文书
学校食堂标语
2014/10/06 职场文书
副检察长四风问题对照检查材料思想汇报
2014/10/07 职场文书
英文慰问信范文
2015/03/24 职场文书
社区艾滋病宣传活动总结
2015/05/07 职场文书
投资申请报告
2015/05/19 职场文书
获奖感言范文
2015/07/31 职场文书
解决jupyter notebook启动后没有token的坑
2021/04/24 Python
JS的深浅复制详细
2021/10/16 Javascript
Html5同时支持多端sdk的小技巧
2021/11/17 HTML / CSS