1. 程式人生 > >關於 DataTables 本地儲存那點事,又愛又恨 (stateSave引數應用)

關於 DataTables 本地儲存那點事,又愛又恨 (stateSave引數應用)

為什麼說又愛又恨?這要從很久很久以前說起……

目錄

  • 愛在哪裡?

說實在的stateSave 這個還是 DataTables 一個比較好的功能,儲存上次分頁狀態,資料上次排列順序,上次條件過濾的結果……, 這些對於某些開發者來說無疑是非常棒的,所以能不愛嗎?無法抗拒啊

1
2
3
4
5
    $(document).ready(function() {
        var t = $('#example').DataTable({
            "stateSave": true
        });
    });

在初始化的時候如上述程式碼,即可開啟本地狀態儲存的功能。

  • 恨在哪裡?

正是因為他功能如此之強大,導致了其他“靈異事件”。

  • 怎麼重新整理了還是之前的結果?
  • 為什麼我的過濾條件不起作用?
  • 這個排序怎麼沒效果?
  • ……

類似的問題有很多,看到這樣的問題我第一眼需要看的就是你程式碼裡有沒有加這個引數,如果你無意間加了這個引數,那麼問題很簡單,按照以下兩步走:

  • 第一:去掉 stateSave 或者值賦值為 false
  • 第二:清空本地快取

這樣操作後,上面提到的問題就能解決。一般來說超過99%的類似問題都是因為不理解stateSave引數導致的。

從上面這些也反應了一個問題:

知其然不知其所以然,大家確實查詢了資料、看了文件,但是隻是照搬,沒有弄清楚真正的意思,這樣肯定會給自己帶來不少麻煩。

這裡告訴大家一個技巧,一般外掛都有預設值、無引數的初始化方法,這是最基本的需求,而不是自己還要去加這樣或那樣的引數。比如如下程式碼:

1
2
3
    $(document).ready(function() {
        var t = $('#example').DataTable();
    });

只要這樣,DataTables 就可以渲染你的表格,給你的表格加上分頁,排序,過濾。你如果還需要其他功能,通過查詢文件再相應加上相關的屬性。 我極力推薦這種做法,一是自己的程式碼很簡潔,二是不會給自己添麻煩,三是遇到問題後,程式碼貼出去問題也能很快的被解決。

PS:我推薦大家把 

DataTables引數配置模板 仔細看一遍,這樣對DT的引數有個整體的把握,用起來會更得心應手

  • 什麼時候該使用這個引數?

知其然,還得知其所以然。弄清你需要到達什麼樣的目的,你就會去使用他。不過在使用之前,你得知道 stateSave 是什麼意思?

很簡單,你可以簡單理解為快取。他可以快取DT的所有狀態。

比如說有以下應用:

  • 保持翻頁,比如當前翻到第4頁,下次再開啟的時候任然是第4頁
  • 保持排列順序,比如第二列是降序排列,下次再開啟第二列仍是降序排列
  • 保持過濾條件,比如前一次輸入的過濾條件是【DataTables中文網】,再次開啟任然是按照此關鍵字來過濾資料
  • …… 當然不止我上面所提到的這些,大家可以天馬行空,發揮自己的想象,沒有做不到,只有想不到,做到做不到,試試就知道

  • 示例講解

    下面通過具體的例子告訴大家 DT 究竟是怎麼儲存狀態的

一個簡單的例子演示了幾個回撥函式之間是怎麼執行的,執行順序如何?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
$("#example").DataTable({
    //開啟本地儲存功能

    stateSave: true,
    //儲存狀態操作

    "stateSaveParams": function (settings, data) {
        console.log("stateSaveParams");
        
        //這裡可以操作儲存的資料,寫上自己特定的邏輯

        //data.search.search = "";

    },
    "stateSaveCallback": function (settings, data) {
        console.log("stateSaveCallback");
        
        //DT預設儲存的key值為DataTables_+表格id+頁面名稱

        localStorage.setItem('DataTables_' + settings.sInstance, JSON.stringify(data));

        // 你可以把這些資料儲存在伺服器上,上面的程式碼標識使用本地儲存來儲存這些資料

        /**$.ajax( {
                "url": "/state_save",
                "data": data,
                "dataType": "json",
                "type": "POST",
                "success": function () {}
            } );
         **/


    },

    //讀取狀態操作

    "stateLoadParams": function (settings, data) {
        console.log("stateSaveParams");

        //在讀取資料的時候可以改變資料,根據自己邏輯來處理

        //data.search.search = "";


        //或者你可以直接禁用從快取裡讀取資料,只要直接返回false即可

        //return false;

    },
    "stateLoadCallback": function (settings) {
        console.log("stateLoadCallback");
        return JSON.parse(localStorage.getItem('DataTables_' + settings.sInstance));

        //同樣你還可以從伺服器取數,採用同步的方式獲取到儲存在伺服器裡的資料

        /**var o;
         $.ajax( {
            "url": "/state_load",
            "async": false,
            "dataType": "json",
            "success": function (json) {
                o = json;
            }
        } );
         return o;**/

    },
    //狀態載入完後執行的回撥函式

    "stateLoaded": function (settings, data) {
        console.log("stateLoaded");

        //在這裡你可以打印出儲存的快取資料

        //alert( 'Saved filter was: '+data.search.search );


    },
    "ajax": {
        "url": "/objects.txt"
    },
    "columns": [
        {"data": "name"},
        {"data": "position"},
        {"data": "salary"},
        {"data": "start_date"},
        {"data": "office"},
        {"data": "extn"}
    ],
    "language": {
        "lengthMenu": "每頁_MENU_ 條記錄",
        "zeroRecords": "沒有找到記錄",
        "info": "第 _PAGE_ 頁 ( 總共 _PAGES_ 頁 )",
        "infoEmpty": "無記錄",
        "search": "搜尋:",
        "infoFiltered": "(從 _MAX_ 條記錄過濾)",
        "paginate": {
            "previous": "上一頁",
            "next": "下一頁"
        }
    },
    "dom": "<'row'<'col-xs-2'l><'#mytool.col-xs-4'><'col-xs-6'f>r>" +
    "t" +
    "<'row'<'col-xs-6'i><'col-xs-6'p>>"
});

執行順序如下:

儲存

  • stateSaveParams
  • stateSaveCallback

讀取

  • stateLoadParams
  • stateLoadCallback
  • stateLoaded

PS:如果對此還有疑問的,大家可以clone下面提到的完整工程,自己試驗最終的結果

下面的 JSON 資料為 DT 定義的格式,按照此要求來儲存和讀取表格的狀態,達到快取的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
    "time":   {number}               // 時間戳,狀態創建立、修改的時間

    "start":  {number}               // 顯示起始位置

    "length": {number}               // 每頁顯示的條數

    "order":  {array}                // 二維陣列,用來描述那些列按照什麼要求排序

    "search": {
        "search":          {string}  // 搜尋條件

        "regex":           {boolean} // 是否支援正則表示式

        "smart":           {boolean} // 是否開啟了智慧搜尋

        "caseInsensitive": {boolean} // 不區分大小寫

    },
    "columns" [
        {
            "visible": {boolean}     // 列是否隱藏顯示

            "search":  {             // 包含每列的單獨搜尋條件,格式和上面的一致

                "search":          {string}  // 搜尋條件

                "regex":           {boolean} // 是否支援正則表示式

                "smart":           {boolean} // 是否開啟了智慧搜尋

                "caseInsensitive": {boolean} // 不區分大小寫

            }           
        },
        ……
    ]
}

再貼上一個例項的真實資料樣例,完整的工程點我

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{
  "time": 1475739393071,
  "start": 0,
  "length": 10,
  "order": [
    [
      5,
      "asc"
    ]
  ],
  "search": {
    "search": "Developer",
    "smart": true,
    "regex": false,
    "caseInsensitive": true
  },
  "columns": [
    {
      "visible": true,
      "search": {
        "search": "",
        "smart": true,
        "regex": false,
        "caseInsensitive": true
      }
    },
    {
      "visible": true,
      "search": {
        "search": "",
        "smart": true,
        "regex": false,
        "caseInsensitive": true
      }
    },
    {
      "visible": true,
      "search": {
        "search": "",
        "smart": true,
        "regex": false,
        "caseInsensitive": true
      }
    },
    {
      "visible": true,
      "search": {
        "search": "",
        "smart": true,
        "regex": false,
        "caseInsensitive": true
      }
    },
    {
      "visible": true,
      "search": {
        "search": "",
        "smart": true,
        "regex": false,
        "caseInsensitive": true
      }
    },
    {
      "visible": true,
      "search": {
        "search": "",
        "smart": true,
        "regex": false,
        "caseInsensitive": true
      }
    }
  ]
}

上面的資料表示當你下次重新重新整理頁面後,表格將顯示如下描述所示:

  • 從第一條資料顯示,每頁顯示10條資料
  • 第6列升序排列
  • 全域性過濾條件為”Developer”,不支援正則,支援智慧搜尋,區分大小寫
  • 六列都顯示,沒有單獨的過濾條件

PS:在實際操作過程中,如果是多列同時排序 order 儲存的資料如下:[[5,"asc",0],[4,"desc",0]] , 由於作者沒有文件說明第三個 數字代表什麼,我猜測這是用來確定排序優先順序的引數,具體大家可以檢視原始碼,作者是怎麼解析第三個數字的

  • 總結

說了這麼多,大家可能終於明白了 stateSave 究竟是什麼意思了。看完了這篇文章,大家同意這篇文章的標題裡說的【又愛又恨】嗎?