Vue 结合Sortablejs实现table行排序功能

 更新时间:2022年10月26日 11:38:02   作者:马永猛  
在一个列表展示页面上,使用了表格组件,原有组件本身不支持拖拽功能,需求要求在列表的基础上支持行拖拽排序,因此引入了www.sortablejs.com插件,接下来通过本文给大家讲解Vue 结合Sortablejs实现table行排序功能,需要的朋友可以参考下

Sortable.js是一款轻量级的拖放排序列表的js插件(虽然体积小,可是功能很强大)

官方Demo:http://rubaxa.github.io/Sortable/

场景

在一个列表展示页面上,使用了表格组件,原有组件本身不支持拖拽功能,需求要求在列表的基础上支持行拖拽排序。因此引入了www.sortablejs.com插件。

问题

引入Sortablejs后刚开始都很顺利,效果的拖拽基本功能效果已实现。代码如下

const tbody = this.$refs.Scheduling.querySelectorAll('.ant-table-tbody') // 元素选择器名称根据实际内容替换
Sortable.create(tbody[0]) //具体Sortablejs的api文档可查看官网

下一步就是保存数据
但是在保存数据的时候才发现,数据并没有修改,还是原来的数据,接下来就来处理数据排序的问题,经查看Sortablejs文档引入了onEnd方法,也可用onUpdate方法
代码修改如下

 const tbody = this.$refs.Scheduling.querySelectorAll('.ant-table-tbody') // 元素选择器名称根据实际内容替换
  const _this = this
    Sortable.create(tbody[0], {
      onEnd({ newIndex, oldIndex }) {
      const currRow = _this.databases.splice(oldIndex, 1)[0]
      _this.databases.splice(newIndex, 0, currRow)
      }
    })

修改完之后本以为可以了,就去调试一下,就出现了比较诡异的问题。A和B拖拽交换位置之后,B和A又神奇的换回去了,整体都乱套了!很奇怪。
经查看资料才发现
Vue的实现原理,在Vue2.0之前是通过defineProperty依赖注入和跟踪的方式实现双向绑定。针对v-for数组指令,如果指定了唯一的Key,则会通过高效的Diff算法计算出数组内元素的差异,进行最少的移动或删除操作。而Vue2.0之后在引入了Virtual Dom之后,Children元素的Dom Diff算法和前者其实是相似的,唯一的区别就是,2.0之前Diff直接针对v-for指令的数组对象,2.0之后则针对Virtual Dom。DOM Diff算法在这里不再赘述,这里解释的比较清楚virtual-dom diff算法
假设我们的列表元素数组是[‘A','B','C','D']
渲染出来后的DOM节点是[$A,$B,$C,$D]
那么Virtual Dom对应的结构就是[{elm:$A,data:'A'},
{elm:$B,data:'B'},
{elm:$C,data:'C'},
{elm:$D,data:'D'}]
假设拖拽排序之后,真实的DOM变为[$B,$A,$C,$D]
此时我们只操作了真实DOM,改编了它的位置,而Virtual Dom的结构并没有改变,依然是[{elm:$A,data:'A'},
{elm:$B,data:'B'},
{elm:$C,data:'C'},
{elm:$D,data:'D'}]
此时我们把列表元素也按照真实DOM排序后变成[‘B','A','C','D']
这时候根据Diff算法,计算出的Patch为,VNode前两项是同类型的节点,所以直接更新,即把$A节点更新成$B,把$B节点更新成$A,真实DOM又变回了[$A,$B,$C,$D]
所以就出现了拖拽之后又被Patch算法更新了一次的问题,操作路径可以简单理解为
拖拽移动真实DOM -> 操作数据数组 -> Patch算法再更新真实DOM
根本原因
根本原因是Virtual DOM和真实DOM之间出现了不一致。
所以在Vue2.0以前,因为没有引入Virtual DOM,这个问题是不存在的。
在使用Vue框架的时候要尽量避免直接操作DOM

最后修改代码如下

 onEnd({ newIndex, oldIndex }) {
         const currRowdom = tbody[0].children[newIndex]
         const oldRowdom = tbody[0].children[oldIndex]
         tbody[0].removeChild(currRowdom)
         if (newIndex > oldIndex) {
          tbody[0].insertBefore(currRowdom, oldRowdom)
        } else {
          tbody[0].insertBefore(currRowdom, oldRowdom.nextSibling)
        }

        const currRow = _this.databases.splice(oldIndex, 1)[0]
        _this.databases.splice(newIndex, 0, currRow)
        }

到此这篇关于Vue 结合Sortablejs实现table行排序 的文章就介绍到这了,更多相关vue table行排序 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue 导出文件,携带请求头token操作

    vue 导出文件,携带请求头token操作

    这篇文章主要介绍了vue 导出文件,携带请求头token操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • 完美解决vue 项目开发越久 node_modules包越大的问题

    完美解决vue 项目开发越久 node_modules包越大的问题

    这篇文章主要介绍了vue 项目开发越久 node_modules包越大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • Vue组件间通信方式全面汇总介绍

    Vue组件间通信方式全面汇总介绍

    这篇文章主要介绍了Vue组件间通信方式全面汇总,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2023-04-04
  • Vue.js数据绑定之data属性

    Vue.js数据绑定之data属性

    这篇文章主要为大家详细介绍了Vue.js数据绑定之data属性,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • vue+echarts图表的基本使用步骤总结

    vue+echarts图表的基本使用步骤总结

    这篇文章主要给大家介绍了关于vue+echarts图表的基本使用步骤,Echarts是一款基于JavaScript的开源可视化图表库,而Vue是一种流行的JavaScript框架,用于构建用户界,需要的朋友可以参考下
    2023-11-11
  • 基于vue打包后字体和图片资源失效问题的解决方法

    基于vue打包后字体和图片资源失效问题的解决方法

    下面小编就为大家分享一篇基于vue打包后字体和图片资源失效问题的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • vue实现简易计算器功能

    vue实现简易计算器功能

    这篇文章主要为大家详细介绍了vue实现简易计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • Vue中如何给Window对象添加方法

    Vue中如何给Window对象添加方法

    这篇文章主要介绍了Vue中如何给Window对象添加方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • Vue关键字搜索功能实战小案例

    Vue关键字搜索功能实战小案例

    在vue项目中,搜索功能是我们经常需要使用的一个场景,下面这篇文章主要给大家介绍了关于Vue关键字搜索功能的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • Vue中使用h5 Plus的实现方法

    Vue中使用h5 Plus的实现方法

    这篇文章主要介绍了Vue中使用h5 Plus的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10

最新评论