el-table行拖拽(SortTablejs)

SortTable实现el-table行拖拽

SortTableJS官网

准备工作

安装:element UI

npm i element-ui -S

安装:sorttablejs

npm install sortablejs --save

我这里直接在html中的demo,模板样式如下:

<!-- 
    el-table 行拖拽拖拽 
    1、同表单内拖拽位置
    2、两个表单内互拖
-->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>行拖拽拖拽</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script src="../libs/sortTable/SortTable.min.js"></script>

    <style>
        .box {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        .box1 {
            height: 350px;
            width: 45%;
            float: left;
            margin: 15px 5px;
            border: 1px solid grey;
        }

        /* 修改el-table的显示区域 */
        .el-table__body {
            height: 350px;
            width: 100%;
        }

        .el-table__empty-block {
            display: none;
        }
    </style>
</head>

<body>
    <div id="app" class="box">
        <div class="box1">
            <el-table class="tab1" :data="table1Data" border height="350" style="width: 100%">
                <el-table-column prop="date" label="日期" width="180">
                </el-table-column>
                <el-table-column prop="name" label="姓名" width="180">
                </el-table-column>
                <el-table-column prop="address" label="地址">
                </el-table-column>
            </el-table>
        </div>
        <div class="box1">
            <el-table class="tab2" :data="table2Data" border height="350" style="width: 100%">
                <el-table-column prop="date" label="日期" width="180">
                </el-table-column>
                <el-table-column prop="name" label="姓名" width="180">
                </el-table-column>
                <el-table-column prop="address" label="地址">
                </el-table-column>
            </el-table>
        </div>
    </div>

    <script>
        new Vue({
            el: "#app",
            data() {
                return {
                    table1Data: [{
                        pkid: "001",
                        date: '2016-05-02',
                        name: '王小虎',
                        address: '上海市普陀区泥沙江路 1518 弄'
                    }, {
                        pkid: "002",
                        date: '2016-05-04',
                        name: '张三',
                        address: '上海市普陀区金沙江路 1517 弄'
                    }, {
                        pkid: "003",
                        date: '2016-05-01',
                        name: '李四',
                        address: '上海市普陀区黄土江路 1519 弄'
                    }, {
                        pkid: "004",
                        date: '2016-05-03',
                        name: '王麻子',
                        address: '上海市普陀区水泥路 1516 弄'
                    }, {
                        pkid: "005",
                        date: '2016-05-08',
                        name: '赵四',
                        address: '上海市普陀区水泥路 1516 弄'
                    }],
                    table2Data: [],
                };
            },
        });
    </script>
</body>

</html>

单table表内拖拽

先实现当前table内实现拖动,查看官网,发现sorttablejs配置项中有很多情况的配置,我们就根据自己的需求来选取,我这里只是内部变动,我就找到一个事件:列表内元素顺序更新的时候触发onUpdate() {}, 当然onEnd(){}也能实现,可是看他的说明他是每种情况结束都会执行,我们待会还有其他的要求,就不使用它。

// 列表内元素顺序更新的时候触发
onUpdate: function (/**Event*/evt) {
    // same properties as onEnd
},

在我们改变拖动的时候发现他会把html元素一并移动了,这个不是我们想要的,我们只关注数据列的改变,因为我们在实际使用中也许要使用改变后的数据去做一些事情,所以我们在onUpdate时就要处理数据。

onUpdate: function ({ newIndex, oldIndex }) {
   // 相等不用管
    if (newIndex == oldIndex) {
        return;
    }
    // 拿到改变前的数据待会插入到新位置,删除原位置
    let temp = list[oldIndex];
    list.splice(oldIndex, 1);
    list.splice(newIndex, 0, temp);
}

到这就查看一下就可以发现我们已经可以拖动了🤣🤣🤣
然而根据剧情的发展,不出意外的话,意外就要来了,不知你在拖动时是否发现问题:
拖动前:
记住该图片各个人物的名字位置不要眨眼
记住该图片各个人物的名字位置不要眨眼,看好拖动后的情形:把王小虎拖动到第三行位置
在这里插入图片描述
意外来的总是很突然,这里就有一个关键:el-table :row-key(不会加的可以去阅读一下elementUI的table,row-key最好给他的值为主键这些唯一的)
也就是主键,确保他的唯一,加上之后就会发现,哇,成功了
刷新:把王小虎拖动到第三行位置,一切正常了
在这里插入图片描述

两个table互拖

第一个会了,第二不也一样手到擒来么,上边html也看到了我写了两个table。
继续查询sorttablejs配置项我们又发现了:元素从一个列表拖拽到另一个列表(onAdd)

// 元素从一个列表拖拽到另一个列表
onAdd: function (/**Event*/evt) {
    // same properties as onEnd
},

编写了实现之后如下:

onAdd: function (evt) {
		// evt中包含了原位置下标,新位置下标的信息,具体可以自己打印一看
        // 添加目标数据
        // oldObj另一张表中被拖动的元素
        list.splice(evt.newIndex, 0, oldObj);

		// 拿到被拖动的数组,然后删除被移走的元素
        let sourceData = oldData;
        sourceData.splice(evt.oldIndex, 1);
},

看到上边想法应该是很简单的就实现了,但是你会发现有些数据这里拿不到,这里不同于同表里移动它的传入的list数据都是同一个集合,这里的确是两个,而且打印发现我们从tab1拖到tab2,onAdd里边的list是tab2的,就意味着我们拿不到tab1的???
是这样吗?好像是的,但是有问题我们就解决问题,既然直接地解决方法没有,我们就用间接的,再次查询官方文档发现:

// 开始拖拽的时候
onStart: function (/**Event*/evt) {
    evt.oldIndex;  // element index within parent
},

开始拖拽触发事件,开始拖拽肯定就是tab1了,因此我们可以把它的记录存放

// 在开始拖动的时候我们记录下他拖拽的是哪个元素(className)
_this.dataTrans = elClass;

// 根据classname去获取各自的list
function getSourceData(elClass) {
	// if () {} else if () {} ...这里可以好多好多
	if (elClass == "tab1") {
		return this.table1Data;
	}
	return this.table2Data;
}
// 开始拖拽的时候
onStart: function (/**Event*/evt) {
    let oldElClass = _this.dataTrans;
    if (oldElClass) {
        let oldList = getSourceData(oldElClass);
        let oldObj = oldList[evt.oldIndex];
        // 添加目标数据
        list.splice(evt.newIndex, 0, oldObj);

        oldList.splice(evt.oldIndex, 1);
    }
},

再次拖拽:
在这里插入图片描述

查看打印出来的结果:
在这里插入图片描述
最终顺序和每个table的值都对了。

有一个不足就是拖拽到空表时,需要放到表头下边那条线上才放的进去,本人前端不是很能,只能这样,有能力的可以帮忙修改。

附上完整源码:
需要导入的工具:elementUI,sorttablejs, vue,自己可以下载安装

<!-- 
    el-table 行拖拽拖拽 
    1、同表单内拖拽位置
    2、两个表单内互拖
-->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>行拖拽拖拽</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script src="../libs/sortTable/SortTable.min.js"></script>

    <style>
        .box {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }

        .box1 {
            height: 350px;
            width: 45%;
            float: left;
            margin: 15px 5px;
            border: 1px solid grey;
        }

        .el-table__empty-block {
            display: none;
        }
    </style>
</head>

<body>
    <div id="app" class="box">
        <button type="button" @click="btnClick">Click</button>
        <div class="box1">
            <el-table class="tab1" :data="table1Data" row-key="pkid" border height="350" style="width: 100%">
                <el-table-column prop="date" label="日期" width="180">
                </el-table-column>
                <el-table-column prop="name" label="姓名" width="180">
                </el-table-column>
                <el-table-column prop="address" label="地址">
                </el-table-column>
            </el-table>
        </div>
        <div class="box1">
            <el-table class="tab2" :data="table2Data" row-key="pkid" border height="350" style="width: 100%">
                <el-table-column prop="date" label="日期" width="180">
                </el-table-column>
                <el-table-column prop="name" label="姓名" width="180">
                </el-table-column>
                <el-table-column prop="address" label="地址">
                </el-table-column>
            </el-table>
        </div>
    </div>

    <script>
        new Vue({
            el: "#app",
            data() {
                return {
                    table1Data: [{
                        pkid: "001",
                        date: '2016-05-02',
                        name: '王小虎',
                        address: '上海市普陀区泥沙江路 1518 弄'
                    }, {
                        pkid: "002",
                        date: '2016-05-04',
                        name: '张三',
                        address: '上海市普陀区金沙江路 1517 弄'
                    }, {
                        pkid: "003",
                        date: '2016-05-01',
                        name: '李四',
                        address: '上海市普陀区黄土江路 1519 弄'
                    }, {
                        pkid: "004",
                        date: '2016-05-03',
                        name: '王麻子',
                        address: '上海市普陀区水泥路 1516 弄'
                    }, {
                        pkid: "005",
                        date: '2016-05-08',
                        name: '赵四',
                        address: '上海市普陀区水泥路 1516 弄'
                    }],
                    table2Data: [],
                    dataTrans: null,
                };
            },
            mounted() {
                this.sortTableFun("tab1", this.table1Data);
                this.sortTableFun("tab2", this.table2Data);
            },
            methods: {
                sortTableFun(elClass, list) {
                    const _this = this;
                    const el = document.querySelector(`.${elClass} .el-table__body-wrapper tbody`);
                    Sortable.create(el, {
                        group: {
                            name: "tabGroup",
                            pull: true,
                            put: true
                        },
                        amimation: 180,
                        onStart: function (/**Event*/evt) {
                            _this.dataTrans = elClass;
                        },
                        onUpdate: function ({ newIndex, oldIndex }) {
                            // 相等不用管
                            if (newIndex == oldIndex) {
                                return;
                            }
                            let temp = list[oldIndex];
                            list.splice(oldIndex, 1);
                            list.splice(newIndex, 0, temp);
                        },
                        onAdd: function (evt) {
                            let oldElClass = _this.dataTrans;
                            if (oldElClass) {
                                let oldList = getSourceData(oldElClass);
                                let oldObj = oldList[evt.oldIndex];
                                // 添加目标数据
                                list.splice(evt.newIndex, 0, oldObj);

                                oldList.splice(evt.oldIndex, 1);
                            }
                        },
                    });

                    // 根据classname去获取各自的list
                    function getSourceData(elClass) {
                        // if () {} else if () {} ...这里可以好多好多
                        if (elClass == "tab1") {
                            return _this.table1Data;
                        }
                        return _this.table2Data;
                    }
                },
                btnClick() {
                    console.log({ tab1: this.table1Data, tab2: this.table2Data });
                }
            }
        });
    </script>
</body>

</html>
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值