基于vue-draggable 的三级拖动排序

vue-draggable 

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

废话少说直接上代码

先看数据结构,和页面的呈现,等会再来上代码。
基于vue-draggable 的三级拖动排序_第1张图片

基于vue-draggable 的三级拖动排序_第2张图片

这就是三层结构渲染出来的图。那个海锚一样的东西是可以点击的,点击后会出现当前类型所带的产品。等会会说的
我们现在来看下我实现后的拖动效果,如下

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

控制台的打印


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

先上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-draggable 的三级拖动排序_第3张图片
然后是使用vue把vuedraggable模块引入,上面图最下面的js是我刚刚发过的代码文件。

Vue.component('vue-draggable', vuedraggable)
这句话显得尤为重要。注册成vue的组件,虽然它本身就是vue的一个组件了。
基于vue-draggable 的三级拖动排序_第4张图片

当然最后我们会进行排序后的顺序的保存。这里就不得不说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;
    }

jdk8语法,可能还有需要改进的地方。反正目前来说,功能是实现了。
其实本来想代码一点点讲解的,奈何实在是有事。

 

关于怎么让3级菜单组件相互拖动,你只需要在父级相互拖动这里就能找到答案,
基于vue-draggable 的三级拖动排序_第5张图片

加上这个属性就行,理论上。我没试过,因为我懒,hhhh
有问题可以在评论留言。
roger

你可能感兴趣的:(记录,js,页面,vuedraggable,vue,拖动排序)