vue数据穿梭框自定义排序

吐槽

最近项目使用vue+element-ui做后台,其中有个功能用到了数据穿梭框,刚好element里有,原本相安无事(哈哈),突然老大说要对选择中的列来个自定义排序(当时我就老不乐意了,我一个后端兼职前端这么久了,用用前端框架就差不多了啊,现在功能都写完了,突然多了这个功能,element的兄弟有没提供,这是要换插件的节奏啊),于是爱恨交错人憔悴,怕只怕这需求推不掉。百度,bing,google,苦心人天不负


欲哭无泪,你怎么能改需求呢,不厚道。接着翻N多帖子,全特么标题党,待解决,个别靠谱的要改源码(看起来好复杂,不敢试)
那么,只能自己动手丰衣足食了。

效果图


知识点

大佬对数组的总结,搬过来占坑

方法 说明 实例
push( ); 在原来数组中的元素最后面添加元素 arr.push(“再见58”);
unshift( ); 在原来数组中的元素最前面添加元素 arr.shift(“你好58”);
pop(); 移除数组中最后面的一个元素 arr.pop();
shift(); 移除数组中最前面的一个元素 arr.shift();
concat(); 拼接两个数组中的元素(哪个数组在前面,拼接后它的元素就在前面) arrA.concat(arrB);
join(" "); 把数组转换为字符串(将数组中的元素通过特殊符号链接成字符串) arr.join("*");
split(" "); 把字符串转为数组(通过字符串的某个特定符号或者字母拆分为数组的元素) txtStr = “avbvcvdvevf”;txtStr.split(“v”);

这些方法在上移下移置顶置底的时候将会用到

代码实现

这里写了一个组件(js版的,不是前端小伙伴用到的*.vue)
用法:

<warmer-transfer  :sourcedata="sourcedata" sourcetitle="源列表" :targetdata="targetdata" targettitle="目标列表"></warmer-transfer>

warmer-transfer.js

Vue.component('warmer-transfer', {
    props: ['sourcedata','sourcetitle','targetdata','targettitle'],
    data: function () {
        return {
            sourceList: [],
            targetList: [],
        };
    },
    filters: {},
    computed: {
        // 源数据中选中的数量
        sourceRefNum() {
            return this.sourceList.filter(item => item.isSelected).length;
        },
        // 目标数据中选中的数量
        targetRefNum() {
            return this.targetList.filter(item => item.isSelected).length;
        },
        // 选择的源记录数量
        selectSourceItemNumber() {
            return this.sourceList.filter(item => item.isSelected).length;
        },
        // 选择目标记录数量
        selectTargetItemNumber() {
            return this.targetList.filter(item => item.isSelected).length;
        },
    },
    created() {
        if(this.targetdata===null||this.targetdata.length===0){
            this.sourceList = this.formatData(val);
            return;
        }
        var source=[];
        var target=this.targetdata;
        this.sourcedata.forEach(function (item) {
            let data = target.filter(n => n.name==item.name);
            if(data==null||data.length==0){
                source.push(item);
            }
        })
        this.sourceList = this.formatData(source);
        this.targetList = this.formatData(this.targetdata);
    },
    watch: {

    },
    mounted() {

    },
    methods: {
        formatData(dataList) {
            let data = dataList.map(item => {
                return {
                    ...item,
                    isSelected: false
                };
            });
            return data;
        },
        moveItems(direction) {
            let selectedItem = this.targetList.filter(item => item.isSelected).map(item => {
                return item.name;
            });
            if (direction == 1) {//下移
                for (var i = selectedItem.length - 1; i >= 0; i--) {
                    let index = this.targetList.map(item => {
                        return item.name;
                    }).indexOf(selectedItem[i]);
                    if (index >= this.targetList.length - 1) return;
                    this.targetList[index] = this.targetList.splice(index + 1, 1, this.targetList[index])[0];
                }
            }
            if (direction == 0) {//上移
                for (var i = 0; i < selectedItem.length; i++) {
                    let index = this.targetList.map(item => {
                        return item.name;
                    }).indexOf(selectedItem[i]);
                    if (index <= 0) return;
                    this.targetList[index] = this.targetList.splice(index - 1, 1, this.targetList[index])[0];
                }
            }
            if (direction == 3) {//置底
                for (var i = 0; i < selectedItem.length; i++) {
                    let index = this.targetList.map(item => {
                        return item.name;
                    }).indexOf(selectedItem[i]);
                    if (index >= this.targetList.length - 1) return;
                    this.targetList.push(this.targetList[index]);
                    this.targetList.splice(index, 1);
                }
            }
            if (direction == 4) {//置顶
                for (var i = selectedItem.length - 1; i >= 0; i--) {
                    let index = this.targetList.map(item => {
                        return item.name;
                    }).indexOf(selectedItem[i]);
                    if (index <= 0) return;
                    this.targetList.unshift(this.targetList[index]);
                    this.targetList.splice(index + 1, 1);
                }
            }
        },
        exchange(fd, td) {
            let selectedItem = fd.filter(item => item.isSelected).map(item => {
                return {
                    ...item,
                    isSelected: false
                };
            });
            td.push(...selectedItem);
            var selectedlist = fd.filter(item => !item.isSelected);
            return selectedlist;
        },
        // 全选状态
        selectedAllStatus(type) {
            if (type == 0) {
                if (this.selectSourceItemNumber === this.sourceList.length && this.selectSourceItemNumber !== 0) {
                    return true;
                } else {
                    return false;
                }
            }
            else {
                if (this.selectTargetItemNumber === this.targetList.length && this.selectTargetItemNumber !== 0) {
                    return true;
                } else {
                    return false;
                }
            }
        },
        // 全选及反选
        toggleAll(type) {
            if (type == 0) {
                let len = this.sourceList.length;
                let slen = this.sourceList.filter(item => item.isSelected).length;
                if (len !== slen) {
                    this.sourceList.map(item => (item.isSelected = true));
                } else {
                    this.sourceList.map(item => (item.isSelected = false));
                }
            } else {
                let len = this.targetList.length;
                let slen = this.targetList.filter(item => item.isSelected).length;
                if (len !== slen) {
                    this.targetList.map(item => (item.isSelected = true));
                } else {
                    this.targetList.map(item => (item.isSelected = false));
                }
            }
        },
        // 把选择数据转移到目标(右框)
        toTarget() {
            this.sourceList = this.exchange(this.sourceList, this.targetList);
        },
        // 把选择数据转回到源(左框)
        toSource() {
            this.targetList = this.exchange(this.targetList, this.sourceList);
        }
    },
    template:
        `
        
全选
{{sourcetitle}} {{selectSourceItemNumber}}/{{sourceList.length}}
全选
{{targettitle}} {{selectTargetItemNumber}}/{{targetList.length}}
`
})

源码下载

GitHub

参考资料

大佬的穿梭框,这个不带排序,完美实现穿梭功能,萌新膜拜,我是大佬的搬运工

告辞

所以到最后,还是相当于换了个插件,哈哈哈

你可能感兴趣的:(vue,数据穿梭框,vue,datatransfer,穿梭框)