vue-draggable
之前项目中需要用到拖动排序,就去网上找资料,本来最开始是想用jquery-ui里的拖动的,后面发现不符合我的预期也不知道能不能跟vue.js兼容,后面我试过了,单个的可以但是层级太多就不一样了。
废话少说直接上代码
这就是三层结构渲染出来的图。那个海锚一样的东西是可以点击的,点击后会出现当前类型所带的产品。等会会说的
我们现在来看下我实现后的拖动效果,如下
所有父类型里面的产品拖动如下
控制台的打印
好了,放了那么多图,数据结构也发了。接下来我们来上代码和思路。
先上html的代码,这里我的页面是jsp,但是不影响html兼容,项目中途接手,很古老的jsp我也没办法
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
排序
--->>>{{one.name}}
--->>>{{two.name}}
接下来是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把vuedraggable模块引入,上面图最下面的js是我刚刚发过的代码文件。
Vue.component('vue-draggable', vuedraggable)
这句话显得尤为重要。注册成vue的组件,虽然它本身就是vue的一个组件了。
当然最后我们会进行排序后的顺序的保存。这里就不得不说vue的双向绑定了,你对象只要在页面改变位置,在内存地址里的位置顺序也会被改变的,所有我们只需要再次将整个对象回传就行。后台去解析保存,当然这种方式我觉得会很繁琐。比如:我贴个获取数据的代码
/**
* 获取排序数据
*
* @param merchantId
* @return
*/
public List treeSorting(Long merchantId) {
//获取所有的连接项
List typeRefList = productTypeRefService.findAll();
//获取所有的产品
Map productList = productService.sortFindProduct(merchantId).stream().collect(
Collectors.toMap(w -> w.getId(), w -> w));
//最上级父级
List parentList = byParentProduct(merchantId, 0);
//平均未分类
List typeList = byParentProduct(merchantId, 1);
//
//获取产品类型和产品关联
Map> parentIdChildrenMap = typeRefList.stream().filter(productTypeRef -> productTypeRef.getProductTypeId() != null).collect(Collectors.groupingBy(ProductTypeRef::getProductTypeId));
parentList.forEach(p -> {
//筛选第二级菜单
List districtsOne = typeList.stream().filter(sortProductTypeVo -> sortProductTypeVo.getParentTypeId().equals(p.getId())).collect(Collectors.toList());
districtsOne.forEach(a -> {
//第三层菜单
List districtsTwo = typeList.stream().filter(productType -> productType.getParentTypeId().equals(a.getId())).collect(Collectors.toList());
districtsTwo.stream().forEach(d -> {
//获取产品和产品类型之间的连接关系
List 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 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 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;
}
加上这个属性就行,理论上。我没试过,因为我懒,hhhh
有问题可以在评论留言。
roger