项目场景:
vue2中饿了么表格组件中的行数据上下拖拽排序
问题描述
大概讲诉一下我这个功能实现的需求前提,需要在左边的表格中勾选需要的数据,同步到右边的排序表格数据中,然后对勾选出的数据在右边表格中进行上下拖拽排序
原因分析:
容易踩坑的点:
1.需要下载Sortable依赖,使用这个组件库实现表格的拖拽,并且要在页面中引入这个依赖包 下载命令:npm i sortable.js --save
2.需要拖拽的表格外面最好是包裹一个div 加上类名或者id ,方便到时候定位dom元素
3.因为我这个是写在弹窗中 el-dialog,所以获取dom的时候 会有延迟,一开始没发现这个问题,获取dom一直是undefined,解决方法参考下面代码块中 ,mounted中的方法,利用延时器和this.$nextTick加载表格dom(当然如果不是在弹窗中 应该不需要用到这一步,反正根据你实际情况来吧)
4.拖拽表格中有一个非常关键的属性 row-key,这里的值一定要是唯一的 ,一般建议取你数据中的id作为属性值,开始我自己定义假数据测试时,id都写成一样忘了改,后端返回的数据ID也都是一样,结果就出现拖拽有问题,发现这个问题后,就跟后端沟通,让他修改了ID的值为唯一性,所以这个属性是决定你上下拖拽行数据是否成功并且丝滑的关键因素
5.记录一下这里额外的一个功能:
当左边表格勾选数据和右边的数据一样时,对左边的勾选数据有一个去重禁选效果,
可以给排序的那一列 加上:selectable这个方法,通过判断两个表格的重复项为切入点进行去重筛选,这样当右边的表格里和左边表格的数据是一样时,左边的多选框就不能再二次勾选 直接禁用啦
解决方案:
//左侧多选表格 <el-table ref="table" class="selectRow" :loadingM="true" :pagination="false" :maxHeight="400" :data="lefttabledata" @selection-change="selectionChange" > <el-table-column type="selection" width="55px" :selectable="checkSelectable" ></el-table-column> <el-table-column prop="BDP_AREA" label="箱"></el-table-column> <el-table-column prop="BDP_BAYNO" label="倍"></el-table-column> <el-table-column prop="BDP_AVAILABLE_COUNT" label="可用数" ></el-table-column> </el-table> //拖拽的表格 <div style="margin-left: 10px" id="sortableDiv"> <el-table :data="paixutable" stripe row-key="ID" ref="pxtable" highlight-current-row v-loading="dataListLoading" :header-cell-style="headerCellStyle" style="width: 100%" > <el-table-column align="center" label="排序" type="index" ></el-table-column> <el-table-column v-for="(item, index) in col" :key="`col_${index}`" :prop="item.prop" :label="item.label" ></el-table-column> <el-table-column align="center" label="操作"> <template slot-scope="scope"> <el-button type="text" @click="delscope(scope.$index, paixutable)" >删除</el-button > </template> </el-table-column> </el-table> </div>
import Sortable from 'sortablejs'
paixutable: [ //当时这里的id全都是1,忘了更改,结果拖拽一直有问题 // { // id: 1, // BDP_AREA: 'br', // BDP_BAYNO: '02', // BDP_AVAILABLE_COUNT: '3' // }, // { // id: 2, // BDP_AREA: 'ar', // BDP_BAYNO: '06', // BDP_AVAILABLE_COUNT: '5' // }, // { // id: 3, // BDP_AREA: 'rr', // BDP_BAYNO: '01', // BDP_AVAILABLE_COUNT: '9' // }, ], col: [ { label: '箱', prop: 'BPD_ARA' }, { label: '倍', prop: 'BPD_BAYO' }, { label: '可用数', prop: 'BPD_AVAILABLE_CNT' } ],
methods: { // 拖拽排序 rowDrop() { const tableref = this.$refs.pxtable.$el const tbody = tableref.querySelector('#sortableDiv .el-table .el-table__body-wrapper .el-table__body tbody') const _this = this //这个就是拖拽组件库的使用 Sortable.create(tbody, { onEnd: (evt) => { console.log(evt, '拖拽11') const changedata = _this.paixutable.splice(evt.oldIndex || 0, 1) _this.paixutable.splice(evt.newIndex || 0, 0, changedata[0]) console.log(_this.paixutable, '拖拽表格') } }) }, // 左边多选表格勾选数据 selectionChange(val) { // console.log(val, '勾选值') this.selection = val const edittable = this.paixutable var tableselect = [] // 去除多选中的重复项 val.forEach((item) => { if (!edittable.some((e) => e.ID === item.ID)) { tableselect.push({ ID: item['ID'], BPD_AREA: item['BDP_AREA'], BPD_BAYNO: item['BDP_BAYNO'], BPD_AVAILABLE_COUNT: item['BDP_AVAILABLE_CUNT'], BPD_PLANNO: item['BDP_PLANNO'] }) } }) this.paixutable = edittable.concat(tableselect) }, // 重复发箱计划禁选 checkSelectable(rows) { // 使用Array.some()方法遍历this.paixutable数组 const isDisabled = this.paixutable.some(item => { return rows.BDP_AREA === item.BPD_AREA && rows.BDP_BAYNO === item.BPD_BAYNO }) if (isDisabled) { return false // 禁止勾选 } else { return true // 允许勾选 } },}
mounted(){ // 获取拖拽表格的dom setTimeout(() => { this.$nextTick(() => { this.rowDrop() }) }, 3000) }