VUE在项目中使用sortable.js实现el-table表格拖拽,并重新排序

// 拖拽主函数写在method()里。
        // 行拖拽
        dragRow() {
            // 查找要拖拽元素的父容器 ,给你的表格所在的父级页面元素加一个自定义类名 比如dictItemList
            const tbody = document.querySelector('.dictItemList tbody');
            const _this = this;
            Sortable.create(tbody, {
                draggable: ' .el-table__row', //  指定父容器下可被拖拽的子元素
                onEnd({ newIndex, oldIndex }) {
                    /**
                     * onEnd 拖拽结束后的事件处理函数
                     * newIndex:目标位置对应行的索引
                     * oldIndex:被拖拽行的索引
                     *
                     * ====================(被拖拽记录行1)
                     * before
                     * ====================(拖拽至目标位置对应记录行)
                     * after
                     * ====================(被拖拽记录行2)
                     * 如果从上往下拖拽,即newIndex > oldIndex,那么在目标位置对应记录行上移(目标位置对应记录行索引值减1),在newIndex所指位置插入被拖拽行(被拖拽行索引设置为newIndex),视觉效果就是在after位置(即目标位置对应行下方)插入被拖拽行
                     * 如果从下往上拖拽,即newIndex < oldIndex,那么在目标位置对应记录行下移(目标位置对应记录行索引值加1),在newIndex所指位置插入被拖拽行(被拖拽行索引设置为newIndex),视觉效果就是在上述before位置(即目标位置对应行上方)插入被拖拽行
                     * */
                    var sendData = [];
                    //如果人把行从上往下拉
                    if (newIndex > oldIndex) {
                        // 排序值改变算法如下
                        let temp = _this.ItemData[newIndex].sort;
                        for (let i = newIndex; i > oldIndex; i--) {
                            _this.ItemData[i].sort = _this.ItemData[i - 1].sort;
                        }
                        _this.ItemData[oldIndex].sort = temp;
                        //取改变了索引的数据列表
                        var shortData = _this.ItemData.slice(oldIndex, newIndex + 1);
                        sendData = [];
                        //取关键词和排序词
                        for (let m = 0; m < shortData.length; m++) {
                            let obj = {
                                typeCode: shortData[m].typeCode,
                                dictCode: shortData[m].dictCode,
                                sort: shortData[m].sort
                            };
                            sendData.push(obj);
                        }
                        //请求服务器作出数据处理,后端改变排序的值
                        api.moveDictItemUpdateSort(sendData, response => {
                            if (response.data.statusCode === 'API-COMMON-INF-OK') {
                            	//调用查询,重新查数据,返回排序后的数据回显
                                _this.getFreshData();
                            } else {
                                _this.$message.error('排序更新失败');
                            }
                        });
                        sendData = [];
                    }
                    //人把行从下往上拉
                    if (newIndex < oldIndex) {
                        //排序值算法2
                        let temp2 = _this.ItemData[newIndex].sort;
                        for (let j = newIndex; j < oldIndex; j++) {
                            _this.ItemData[j].sort = _this.ItemData[j + 1].sort;
                        }
                        _this.ItemData[oldIndex].sort = temp2;
                        // 请求服务器做数据更新处理 ,然后根据处理结果对前端页面处理
                        shortData = _this.ItemData.slice(newIndex, oldIndex + 1);
                        sendData = [];
                        for (let n = 0; n < shortData.length; n++) {
                            let obj = {
                                typeCode: shortData[n].typeCode,
                                dictCode: shortData[n].dictCode,
                                sort: shortData[n].sort
                            };
                            sendData.push(obj);
                        }
                        api.moveDictItemUpdateSort(sendData, response => {
                            if (response.data.statusCode === 'API-COMMON-INF-OK') {
                                _this.getFreshData();
                            } else {
                                _this.$message.error('排序更新失败');
                            }
                        });
                        sendData = [];
                    }
                }
            });
        },

2.table里面一定要加一个属性 row-key=“dictCode”,不然你拉了之后div不会回归顺序,后端就算排好,你前端也会乱。
3.从后端获取数据函数getFreshData()函数刷新表格,里面一定要加一个
this.$nextTick(() => {
this.dragRow();
});
来触发,不然你就只能自定义按钮来触发拖动了。
4.去写后端代码,用CASE WHEN批量更新数据库或者使用循环SQL即可。
一个拖动功能前后端逻辑就算写好了。

<think>好的,用户的问题是关于在Vue使用el-tablesortable.js实现表格的行和列拖拽排序。我需要先理清用户的具体需求,然后结合提供的引用内容来组织答案。 首先,用户提到了行和列拖拽排序,所以需要分别处理这两个部分。根据引用2和3,行拖拽已经有实现方法,但列拖拽可能需要额外处理。我需要确认sortable.js是否支持列拖拽,或者是否有其他方法。 接下来,分析引用中的信息。引用2和3都提到了使用sortable.jsel-table实现拖拽,但列拖拽没有直接提到。可能需要使用类似的思路,但针对表头进行操作。此外,引用1提到结合Vue 3和Element Plus,但用户可能使用的是Element UI,需要注意版本差异。 然后,我需要考虑具体的实现步骤。对于行拖拽,应该是在tbody绑定Sortable实例,处理行的拖拽事件,更新数据。列拖拽则需要操作thead中的th元素,同样使用Sortable,但需要处理列的重新排列和数据更新。 示例代码部分,需要提供行和列拖拽的代码。行拖拽的代码在引用2和3中有示例,可以借鉴。列拖拽可能需要创建一个新的Sortable实例,作用于表头元素,拖拽结束后更新列的顺序。 注意事项方面,需要注意Vue的响应式数据更新,避免直接操作DOM,而应该通过数据驱动视图。此外,在弹窗中使用时(如引用2提到的el-dialog),可能需要处理组件挂载的时机,确保DOM存在后再初始化Sortable。 另外,用户可能遇到的问题包括拖拽后数据未更新,或者样式问题。需要提醒在拖拽结束后同步数据,处理可能的样式冲突,比如z-index或事件冒泡的问题。 最后,生成相关问题,需要围绕实现中的关键点,如性能优化、事件处理、兼容性等提出相关问题,帮助用户深入理解。 总结步骤: 1. 安装sortable.js 2.拖拽:绑定tbody,处理拖拽事件,更新数据数组 3.拖拽:绑定thead,处理拖拽事件,更新列配置数组 4. 提供示例代码,包括行和列的实现 5. 注意事项:数据同步、组件销毁、样式调整、弹窗中的初始化时机</think>### 分步解答:Vue实现el-table行和列拖拽排序 --- #### **一、实现拖拽排序** 1. **安装依赖** ```bash npm install sortablejs --save ``` 2. **绑定表格行元素** ```vue <template> <el-table :data="tableData" row-key="id" id="dragTable"> <el-table-column label="姓名" prop="name"></el-table-column> <el-table-column label="年龄" prop="age"></el-table-column> </el-table> </template> <script> import Sortable from 'sortablejs'; export default { data() { return { tableData: [ { id: 1, name: '张三', age: 25 }, { id: 2, name: '李四', age: 30 } ] }; }, mounted() { this.initRowSortable(); }, methods: { initRowSortable() { const tbody = document.querySelector('#dragTable tbody'); Sortable.create(tbody, { animation: 150, onEnd: (evt) => { // 同步数据顺序 const data = [...this.tableData]; const [movedRow] = data.splice(evt.oldIndex, 1); data.splice(evt.newIndex, 0, movedRow); this.tableData = data; } }); } } }; </script> ``` --- #### **二、实现拖拽排序** 1. **绑定表头元素** ```vue <template> <el-table :data="tableData" row-key="id" id="dragTable"> <el-table-column v-for="col in columns" :key="col.prop" :label="col.label" :prop="col.prop"></el-table-column> </el-table> </template> <script> export default { data() { return { columns: [ { label: '姓名', prop: 'name' }, { label: '年龄', prop: 'age' } ] }; }, mounted() { this.initColSortable(); }, methods: { initColSortable() { const thead = document.querySelector('#dragTable thead tr'); Sortable.create(thead, { animation: 150, onEnd: (evt) => { // 同步列顺序 const cols = [...this.columns]; const [movedCol] = cols.splice(evt.oldIndex, 1); cols.splice(evt.newIndex, 0, movedCol); this.columns = cols; } }); } } }; </script> ``` --- #### **三、注意事项** 1. **数据同步** 拖拽操作需通过Vue数据驱动视图更新,避免直接操作DOM[^2]。 2. **组件销毁** 在组件销毁时手动清理Sortable实例: ```javascript beforeUnmount() { if (this.rowSortable) this.rowSortable.destroy(); if (this.colSortable) this.colSortable.destroy(); } ``` 3. **弹窗中的使用** 若在`el-dialog`中使用,需在弹窗完全渲染后(如`mounted`或`open`事件)再初始化Sortable。 4. **样式调整** 拖拽时可能出现元素层级问题,可添加CSS: ```css .sortable-chosen { z-index: 9999 !important; } ``` ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值