基于vue-draggable 实现 * 拖动排序效果

作者:慢慢慢慢慢 时间:2024-05-29 22:18:05 

vue-draggable

之前项目中需要用到拖动排序,就去网上找资料,本来最开始是想用jquery-ui里的拖动的,后面发现不符合我的预期也不知道能不能跟vue.js兼容,后面我试过了,单个的可以但是层级太多就不一样了。

废话少说直接上代码

基于vue-draggable 实现 * 拖动排序效果

基于vue-draggable 实现 * 拖动排序效果

先看数据结构,和页面的呈现,等会再来上代码。

这就是三层结构渲染出来的图。那个海锚一样的东西是可以点击的,点击后会出现当前类型所带的产品。等会会说的

我们现在来看下我实现后的拖动效果,如下

基于vue-draggable 实现 * 拖动排序效果

所有父类型里面的产品拖动如下

基于vue-draggable 实现 * 拖动排序效果

控制台的打印

基于vue-draggable 实现 * 拖动排序效果

好了,放了那么多图,数据结构也发了。接下来我们来上代码和思路。

先上html的代码,这里我的页面是jsp,但是不影响html兼容,项目中途接手,很古老的jsp我也没办法


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<link rel="stylesheet" href="${ctx}/res/ifw/plugins/datatables/dataTables.bootstrap.css" rel="external nofollow" />
<style>
[v-cloak] {
display: none;
}
.flip-list-move {
transition: transform 0.5s;
}
.handle {
float: right;
padding-top: 2px;
padding-bottom: 8px;
}
.no-move {
transition: transform 0s;
}
.ghost {
opacity: 0.5;
background: #c8ebfb;
}
.list-group {
min-height: 20px;
}
.list-group-item {
cursor: move;
}
.list-group-item i {
cursor: pointer;
}
</style>
<div id="vueSort" class="box box-darkness">
<div class="box-header with-border">
<h3 class="box-title">排序</h3>
<div class="box-tools pull-right">
 <button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i>
 </button>
</div>
</div>
<div class="box-body" style="position: relative">
<div class="col-md-3">
 <ul id="main-nav1" class="nav nav-tabs nav-stacked">
 <draggable class="list-group" tag="ul" v-model="listProductType":move="getdata" @update="datadragEnd">
  <transition-group type="transition" :name="'flip-list'">
  <li class="list-group-item" v-for="(element,index) in listProductType" :key="element.id">
   <a :href="'#'+forId(element.uuid)" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="nav-header collapsed" data-toggle="collapse"><i
    v-show="element.productList.length>0"
    aria-hidden="true"
    :class="{'fa fa-anchor':isActive,'glyphicon glyphicon-pushpin':!isActive}"
    @click="submenu"></i></a>
   {{element.name}}
   <i class="fa fa-align-justify handle" v-show="element.productTypes.length>0"
   @click="showLeve2(index)"></i>
   <template v-if="element.productList.length>0">
   <ur :id="forId(element.uuid)" class="nav nav-list collapse secondmenu">
    <draggable class="list-group" tag="ul":move="getdata" v-model="element.productList"
     @update="datadragEnds">
    <transition-group type="transition" :name="'flip-list'">
  <li class="list-group-item" v-for="e in element.productList" :key="e.id">
   <a> {{e.name}}</a>
  </li>
  </transition-group>
 </draggable>
 </ur>
 </template>
 </li>
 </transition-group>
 </draggable>
 </ul>
</div>
<div class="col-md-3" v-show="one.productTypes.length>0&&showOne">
 <span><h3 style="color: red">--->>>{{one.name}}</h3></span>
 <ul id="main-nav2" class="nav nav-tabs nav-stacked">
 <draggable class="list-group" tag="ul" v-model="one.productTypes" :move="getdata"@update="datadragEnd">
  <transition-group type="transition" :name="'flip-list'">
  <li class="list-group-item" v-for="(element,index) in one.productTypes" :key="element.id">
   <a :href="'#'+forId(element.uuid)" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="nav-header collapsed" data-toggle="collapse"><i
    v-show="element.productList.length>0"
    aria-hidden="true"
    :class="{'fa fa-anchor':isActive,'glyphicon glyphicon-pushpin':!isActive}"
    @click="submenu"></i></a>
   {{element.name}}
   <i class="fa fa-align-justify handle" v-show="element.productTypes.length>0"
   @click="showLeve3(index)"></i>
   <template v-if="element.productList.length>0">
   <ur :id="forId(element.uuid)" class="nav nav-list collapse secondmenu">
    <draggable class="list-group" tag="ul":move="getdata" v-model="element.productList"
     @update="datadragEnds">
    <transition-group type="transition" :name="'flip-list'">
  <li class="list-group-item" v-for="e in element.productList" :key="e.id">
   <a> {{e.name}}</a>
  </li>
  </transition-group>
 </draggable>
 </ur>
 </template>
 </li>
 </transition-group>
 </draggable>
 </ul>
</div>
<div class="col-md-3" v-show="two.productTypes.length>0&&showTwo">
 <span><h3 style="color: red">--->>>{{two.name}}</h3></span>
 <ul id="main-nav3" class="nav nav-tabs nav-stacked">
 <draggable class="list-group" tag="ul" v-model="two.productTypes":move="getdata" @update="datadragEnd">
  <transition-group type="transition" :name="'flip-list'">
  <li class="list-group-item" v-for="(element,index) in two.productTypes" :key="element.id">
   <a :href="'#'+forId(element.uuid)" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="nav-header collapsed" data-toggle="collapse"><i
    v-show="element.productList.length>0"
    aria-hidden="true"
    :class="{'fa fa-anchor':isActive,'glyphicon glyphicon-pushpin':!isActive}"
    @click="submenu"></i></a>
   {{element.name}}
   <template v-if="element.productList.length>0">
   <ur :id="forId(element.uuid)" class="nav nav-list collapse secondmenu">
    <draggable class="list-group":move="getdata" tag="ul" v-model="element.productList"
     @update="datadragEnds">
    <transition-group type="transition" :name="'flip-list'">
  <li class="list-group-item" v-for="e in element.productList" :key="e.id">
   <a> {{e.name}}</a>
  </li>
  </transition-group>
 </draggable>
 </ur>
 </template>
 </li>
 </transition-group>
 </draggable>
 </ul>
</div>
</div>
<div class="box-footer">
<button type="button" class="btn btn-darkness pull-right" id="doSearch"
 style="margin-left: 20px;"@click="save">保存
</button>
<button type="button" class="btn btn-default pull-right" @click="reset" id="resetSearch">重置</button>
</div>
</div>
<script type="text/javascript" src="${ctx}/res/js/vue/vue.js"></script>
<!-- CDNJS :: Sortable (https://cdnjs.com/) -->
<script src="${ctx}/res/js/vue/Sortable.min.js"></script>
<!-- CDNJS :: Vue.Draggable (https://cdnjs.com/) -->
<script src="${ctx}/res/js/vue/vuedraggable.umd.min.js"></script>
<script type="text/javascript" src="${ctx}/res/js/sort/combinationSort.js"></script>

接下来是js。


Vue.component('vue-draggable', vuedraggable)
var vm = new Vue({
el: '#vueSort',
data: {
isActive: true,
queryObject: {},
listProductType: [],
showSon: false,
index: 0,
one: {productTypes: []},
two: {productTypes: []},
showOne: false,
showTwo: false
},
methods: {
init: function () {
 var _this = this;
 $.ajax({
 url: '../../mt/combinationSort/sortingData',
 data: null,
 type: 'POST',
 contentType: "application/json",
 dataType: 'json',
 success: function (data) {
  if (data.success = true) {
  if (data.dataObject.length == 0) {
   Util.alert('通知', '异常数据', 'info');
   return;
  }
  _this.listProductType = data.dataObject;
  }
  console.log(data)
 }
 })
},
reset: function () {
 var _this = this;
 _this.listProductType = _this.listProductType.sort((one, two) => {
 return one.displaySeq - two.displaySeq;
})
 ;
 for (var i in _this.listProductType) {
 //排序产品类型
 _this.listProductType[i].productTypes = _this.listProductType[i].productTypes.sort((one, two) => {
  return one.displaySeq - two.displaySeq;
 })
 ;
 //排序产品
 _this.listProductType[i].productList = _this.listProductType[i].productList.sort((one, two) => {
  return one.displaySeq - two.displaySeq;
 })
 ;
 for (var a in _this.listProductType[i].productTypes) {
  _this.listProductType[i].productTypes[a].productTypes = _this.listProductType[i].productTypes[a].productTypes.sort((one, two) => {
  return one.displaySeq - two.displaySeq;
 })
  ;
  _this.listProductType[i].productTypes[a].productList = _this.listProductType[i].productTypes[a].productList.sort((one, two) => {
  return one.displaySeq - two.displaySeq;
 })
  ;
  for (var c in _this.listProductType[i].productTypes[a].productTypes) {
  _this.listProductType[i].productTypes[a].productTypes[c].productList = _this.listProductType[i].productTypes[a].productTypes[c].productList.sort((one, two) => {
   return one.displaySeq - two.displaySeq;
  })
  ;
  }
 }
 }
},
datadragEnd: function (evt) {
 console.log('拖动前的索引:' + evt.oldIndex);
 console.log('拖动后的索引:' + evt.newIndex);
 var obj = evt.item;
 obj.style.backgroundColor = '#fff';
},
submenu: function () {
 var _this = this;
 if (_this.isActive) _this.isActive = false;
 else _this.isActive = true;
 if (_this.showSon) _this.showSon = false;
 else _this.showSon = true;
},
datadragEnds: function (evt) {
 console.log('拖动前的索引:' + evt.oldIndex);
 console.log('拖动后的索引:' + evt.newIndex);
 var obj = evt.item;
 obj.style.backgroundColor = '#fff';
},
forId: function (index) {
 return "uuid_" + index
},

showLeve2: function (index) {
 var _this = this;
 _this.index = index;
 // if (_this.one.productTypes.length > 0) _this.one.productTypes = [];
 // else
 _this.one = _this.listProductType[index];
 console.log(_this.one)
 if (_this.showOne) {
 _this.showOne = false;
 _this.showTwo = false;
 }
 else _this.showOne = true;
},
showLeve3: function (index) {
 var _this = this;
 // if (_this.two.productTypes.length > 0) _this.two.productTypes = [];
 // else
 _this.two = _this.listProductType[_this.index].productTypes[index];
 console.log(_this.two.productTypes)
 if (_this.showTwo) _this.showTwo = false;
 else _this.showTwo = true;
},
getdata: function (event) {
 console.log("下来了");
 var obj = event.dragged;
 obj.style.backgroundColor = '#11cc17';
},
save: function () {
 var _this = this;
 Util.confirm('提示', '您确定要保存排序吗?', function (isOk) {
 if (isOk) {
  console.log(_this.listProductType);
  $.ajax({
  type: "post",
  url: "../../mt/combinationSort/saveSortingData",
  data: {list: JSON.stringify(_this.listProductType)},
  success: function (json) {
   console.log(json);
  }
  });
  Util.alert("提示", '保存成功', 'info');
 }
 }, 'info');

}
},
created: function () {
var _this = this;
_this.init();
// _this.heartbeat();
}
});

最重要的是这几行代码

基于vue-draggable 实现 * 拖动排序效果

然后是使用vue把vuedraggable模块引入,上面图最下面的js是我刚刚发过的代码文件。

Vue.component('vue-draggable', vuedraggable)

这句话显得尤为重要。注册成vue的组件,虽然它本身就是vue的一个组件了。

基于vue-draggable 实现 * 拖动排序效果

当然最后我们会进行排序后的顺序的保存。这里就不得不说vue的双向绑定了,你对象只要在页面改变位置,在内存地址里的位置顺序也会被改变的,所有我们只需要再次将整个对象回传就行。后台去解析保存,当然这种方式我觉得会很繁琐。比如:我贴个获取数据的代码


/**
* 获取排序数据
* * @param merchantId
* @return
*/
public List<SortProductTypeVo> treeSorting(Long merchantId) {
//获取所有的连接项
List<ProductTypeRef> typeRefList = productTypeRefService.findAll();
//获取所有的产品
Map<Long, ProductVo> productList = productService.sortFindProduct(merchantId).stream().collect(
 Collectors.toMap(w -> w.getId(), w -> w));
//最上级父级
List<SortProductTypeVo> parentList = byParentProduct(merchantId, 0);
//平均未分类
List<SortProductTypeVo> typeList = byParentProduct(merchantId, 1);
//
//获取产品类型和产品关联
Map<Long, List<ProductTypeRef>> parentIdChildrenMap = typeRefList.stream().filter(productTypeRef -> productTypeRef.getProductTypeId() != null).collect(Collectors.groupingBy(ProductTypeRef::getProductTypeId));
parentList.forEach(p -> {
 //筛选第二级菜单
 List<SortProductTypeVo> districtsOne = typeList.stream().filter(sortProductTypeVo -> sortProductTypeVo.getParentTypeId().equals(p.getId())).collect(Collectors.toList());
 districtsOne.forEach(a -> {
 //第三层菜单
 List<SortProductTypeVo> districtsTwo = typeList.stream().filter(productType -> productType.getParentTypeId().equals(a.getId())).collect(Collectors.toList());
 districtsTwo.stream().forEach(d -> {
  //获取产品和产品类型之间的连接关系
  List<ProductTypeRef> l = parentIdChildrenMap.getOrDefault(d.getId(), new ArrayList<>());
  //排序产品关联就相当于产品排序
  l.sort((q, b) -> Integer.compare(q.getDisplaySeq(), b.getDisplaySeq()));
  //根据排序产品关联去找到产品
  d.setProductList(l.stream().map(e -> {
  ProductVo products = productList.get(e.getProductId());
  if (null != products) products.setDisplaySeq(e.getDisplaySeq());
  return products;
  }).collect(Collectors.toList()).stream().filter(s -> s != null).collect(Collectors.toList()));//数组中过滤空的产品
//   d.setProductTypeRefs(parentIdChildrenMap.getOrDefault(d.getId(), new ArrayList<>()));
 });
 List<ProductTypeRef> l = parentIdChildrenMap.getOrDefault(a.getId(), new ArrayList<>());
 l.sort((q, b) -> Integer.compare(q.getDisplaySeq(), b.getDisplaySeq()));
 a.setProductList(l.stream().map(c -> {
  ProductVo products = productList.get(c.getProductId());
  if (null != products) products.setDisplaySeq(c.getDisplaySeq());
  return products;
 }).collect(Collectors.toList()).stream().filter(s -> s != null).collect(Collectors.toList()));
 districtsTwo.sort((q, b) -> Integer.compare(q.getDisplaySeq(), b.getDisplaySeq()));
 a.setProductTypes(districtsTwo);
//  a.setProductTypeRefs(parentIdChildrenMap.getOrDefault(a.getId(), new ArrayList<>()));
 });
 List<ProductTypeRef> l = parentIdChildrenMap.getOrDefault(p.getId(), new ArrayList<>());
 l.sort((q, b) -> Integer.compare(q.getDisplaySeq(), b.getDisplaySeq()));
 p.setProductList(l.stream().map(a -> {
 ProductVo products = productList.get(a.getProductId());
 if (null != products) products.setDisplaySeq(a.getDisplaySeq());
 return products;
 }).collect(Collectors.toList()).stream().filter(s -> s != null).collect(Collectors.toList()));
//  p.setProductTypeRefs(parentIdChildrenMap.getOrDefault(p.getId(), new ArrayList<>()));
 districtsOne.sort((q, b) -> Integer.compare(q.getDisplaySeq(), b.getDisplaySeq()));
 p.setProductTypes(districtsOne);
});
parentList.sort((q, b) -> Integer.compare(q.getDisplaySeq(), b.getDisplaySeq()));
return parentList;
}

jdk8语法,可能还有需要改进的地方。反正目前来说,功能是实现了。

其实本来想代码一点点讲解的,奈何实在是有事。

关于怎么让3级菜单组件相互拖动,你只需要在父级相互拖动这里就能找到答案,

基于vue-draggable 实现 * 拖动排序效果

加上这个属性就行,理论上。我没试过,因为我懒,hhhh

总结

以上所述是小编给大家介绍的基于vue-draggable 实现 * 拖动排序效果网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

来源:https://blog.csdn.net/qq_37048894/article/details/103908592

标签:vue,draggable,拖动,排序
0
投稿

猜你喜欢

  • 微信小程序学习笔记之本地数据缓存功能详解

    2024-04-22 12:42:49
  • Python编程中使用Pillow来处理图像的基础教程

    2021-07-20 10:53:19
  • 浅谈Go语言的error类型

    2024-05-10 13:57:58
  • python3实现字符串的全排列的方法(无重复字符)

    2022-04-14 19:47:56
  • Python容器类型转换的3种方法实例

    2022-06-03 13:32:32
  • 利用Django框架中select_related和prefetch_related函数对数据库查询优化

    2024-01-20 23:24:19
  • go语言静态库的编译和使用方法

    2024-05-09 09:40:05
  • PHP抽象工厂模式Abstract Factory Pattern优点与实现方式

    2023-05-25 03:04:57
  • Python实现把json格式转换成文本或sql文件

    2022-06-03 14:52:23
  • Python 爬虫模拟登陆知乎

    2023-11-28 14:32:08
  • mysql提示[Warning] Invalid (old?) table or database name问题的解决方法

    2024-01-14 18:18:54
  • 通过字符串导入 Python 模块的方法详解

    2023-10-15 03:00:56
  • jQuery自适应轮播图插件Swiper用法示例

    2024-04-19 10:18:38
  • Vue实现页面添加水印功能

    2024-04-28 09:24:06
  • Python常用内置模块之xml模块(详解)

    2021-12-17 21:31:43
  • Python:Numpy 求平均向量的实例

    2021-09-25 08:01:15
  • python并发编程 Process对象的其他属性方法join方法详解

    2022-03-07 04:29:54
  • Python的地形三维可视化Matplotlib和gdal使用实例

    2021-05-26 13:35:30
  • 详解Selenium 元素定位和WebDriver常用方法

    2021-10-05 01:45:14
  • django echarts饼图数据动态加载的实例

    2023-02-13 21:12:43
  • asp之家 网络编程 m.aspxhome.com