返回

SortableJS保存和重置列表排序:完整指南

javascript

SortableJS:保存和重置列表排序

使用 SortableJS 实现拖拽列表时,我们常需要保存当前排序,并在需要时重置回初始状态。这篇文章会讲清楚如何搞定这个事。

遇到的问题

当前代码尝试使用 alert($('#simpleList').toArray()) 获取排序后的列表项,但只会得到 [object HTMLUListElement]。重置功能也没实现。

问题原因

  • $('#simpleList') 返回的是一个 jQuery 对象,而不是 SortableJS 实例。
  • toArray() 是 SortableJS 实例的方法, 不是Jquery方法。
  • 没有保存初始顺序。

解决方案

我们一步步解决。

1. 获取 SortableJS 实例

首先,需要正确获取 SortableJS 实例。 应该将 Sortable.create() 的返回值存储到一个变量里:

// 初始化可排序列表
var sortable = Sortable.create(simpleList, {
  animation: 150
});

2. 获取当前排序

有了实例,就能用 toArray() 方法获得排序后的 data-id 值数组:

function getCurrentOrder() {
  var order = sortable.toArray();
  alert("当前排序:" + order.join(', '));
}

在HTML里,修改一下"Current order!"按钮的 onclick 事件:

<button type="button" onclick="getCurrentOrder()">Current order!</button>

3. 保存初始排序

为了实现重置, 我们需要在初始化之后、任何拖拽操作之前保存列表的初始状态。 在Sortable.create后立刻获取一下就好。

var sortable = Sortable.create(simpleList, {
  animation: 150
});

var initialOrder = sortable.toArray();

4. 重置排序

重置的原理就是将当前的列表项顺序调整回初始顺序。利用 sort() 方法,配合之前保存的 initialOrder,实现起来很简单:

function resetOrder() {
  sortable.sort(initialOrder);
}

给"Reset!"按钮加上对应的 onclick 事件:

<button type="button" onclick="resetOrder()">Reset!</button>

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<script src="https://raw.githack.com/SortableJS/Sortable/master/Sortable.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>

<!-- Simple List -->
<ul id="simpleList" class="list-group">
  <li data-id="i1" class="col-1">#1</li>
  <li data-id="i2" class="col-2">#2</li>
  <li data-id="i3" class="col-3">#3</li>
  <li data-id="i4" class="col-4">#4</li>
</ul>

<button type="button" onclick="getCurrentOrder()">Current order!</button>
<button type="button" onclick="resetOrder()">Reset!</button>

<script>
//Initiate sortable list
var sortable = Sortable.create(simpleList, {
  animation: 150
});
// Save initial order.
var initialOrder = sortable.toArray();

function getCurrentOrder() {
    var order = sortable.toArray();
     alert("当前顺序是: " + order.join(', '));
}

function resetOrder() {
    sortable.sort(initialOrder);
}
</script>

</html>

进阶用法:持久化存储排序

上面代码只是在当前页面会话有效,刷新就没了.如果想长期保存排序结果,可以用浏览器本地存储(localStorage 或 sessionStorage)或服务器端数据库。

使用 localStorage

localStorage 能把数据长期保存在浏览器里,除非用户手动清除。

  1. 保存排序: 在拖拽结束后,获取当前顺序,并将其存储到 localStorage
var sortable = Sortable.create(simpleList, {
  animation: 150,
  onEnd: function (/**Event*/evt) {
    var currentOrder = sortable.toArray();
    localStorage.setItem('mySortableListOrder', JSON.stringify(currentOrder));
  },
});

onEnd 事件在拖拽完成后触发。

  1. 加载排序: 在页面加载时,从 localStorage 读取排序,并应用到列表:
//Check stored data:
var savedOrder = localStorage.getItem('mySortableListOrder');

if (savedOrder) {
  try
  {
     var orderArray = JSON.parse(savedOrder);
      sortable.sort(orderArray);
  }
    catch(e){ //Deal with parse errors.
       localStorage.removeItem('mySortableListOrder');
  }
}
  1. 注意需要处理可能出现的解析错误, 出现问题的时候,可以直接清除localstorage.

使用服务器端存储

更可靠的方法是将排序数据保存到服务器数据库。大致流程:

  1. 拖拽结束时发送请求: 使用 AJAX(如 fetch 或 jQuery 的 $.ajax)将当前排序发送到服务器。
  2. 服务器端处理: 服务器端接收数据,更新数据库中对应用户的排序记录。
  3. 页面加载时获取排序: 页面加载时,向服务器发送请求,获取该用户的排序数据。
  4. 应用排序: 服务器返回排序数据后,使用 sortable.sort() 方法应用排序。
    这种方法比本地存储好,即使用户换了浏览器或设备也能用.

使用cookie

和Local Storage很像,但有一些不同:

  1. 存储容量限制,远小于Local Storage.
  2. 可以设定过期时间.

存入:

function setSortableCookie(name,value,days) {
    var expires = "";
    if (days) {
        var date = new Date();
        date.setTime(date.getTime() + (days*24*60*60*1000));
        expires = "; expires=" + date.toUTCString();
    }
    document.cookie = name + "=" + (value || "")  + expires + "; path=/";
}

读取

function getSortableCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

删除

function eraseSortableCookie(name) {
    document.cookie = name+'=; Max-Age=-99999999;';
}

使用和Local Storage相似,把localstorage的调用,换成cookie处理就好, cookie比较麻烦的一点在于,cookie会发到服务器,对于性能稍有影响,不过对当前问题影响不大.
同样需要注意错误处理.

总结

要点:

  • 正确获取 SortableJS 实例。
  • 使用 toArray() 获取当前排序的数组。
  • 在初始化后保存一份, 方便后面还原
  • 使用 sort() 方法, 配合存储下来的数据,来重置排序。
  • 根据自己需求决定是不是要把数据存在本地或服务器.