最近一次团队会议中提到了这个问题,感觉有点意思,就有了以下的思考。

我们可以很轻松的写出以下解决思路:

  1. 每一项的数据模型都有一个字段order,表示排序的依据。
  2. 拖拽每一项后对order字段进行一定的变更,并发送修改请求,持久化排序字段。

问题就在于第二步中的 进行一定的变更,是如何变更?
从这一点入手就出现了各种不同的解决方案。

取前后项差值除以2

这是原来旧项目中采用的方案。

  1. 每一项数据初始化一个较大的order值,如:10000、20000、30000…
  2. 拖拽变化后,取前后项的order值相加除以2。假如把第三行拖拽到第一和第二行之间,那么它的order值由30000改为(10000 + 20000) / 2

理论上来讲,如果允许存在浮点数且不限制数据精度,绝对是可取的。退一步来说,也可以在数据临界时,或者某个空闲的时候依照当前顺序对数据库中的order列重新初始化。

这种方案的特点是:新的order值永远在前后项order值的区间内。

由这个特点可以衍生出一些方案,比如:降位法

原始数据:

IDorder
1cE2927ef1C61
8ea5Ed2687A61.1
2c70bADbe43C2
16DA261B24F12.1
4Da27EE5d3de2.2
8ea5Ed2687A62.3
65A64F9c12Ae3

把最后一项放到倒数第二项之前:

IDorder
1cE2927ef1C61
8ea5Ed2687A61.1
2c70bADbe43C2
16DA261B24F12.1
4Da27EE5d3de2.2
65A64F9c12Ae2.21
8ea5Ed2687A62.3

由于2.22.3在十分位上不存在数的间隔,所以插入到之间的项降一位到百分位上。

取前后项的ID

这是由链表数据结构想到的方案。每一项数据记录前一项或后一项的ID,拖拽变化后,进行对应的修改。

缺点

  1. 数据渲染排序阶段开销大。假如取前一项ID为排序依据,需要找到前一项ID为null的为第一行数据,再找出前一项ID为第一行数据ID的为第二行数据…要深度遍历。
  2. 前一项或后一项被删除,需要在删除数据的同时对受影响的排序字段进行数据修复,重新关联前一项或后一项的ID,至少 2 个请求。