成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

localStorage實(shí)現(xiàn)本地儲(chǔ)存樹形菜單

William_Sang / 2737人閱讀

摘要:因?yàn)槿蝿?wù)需要添加到樹的結(jié)構(gòu)上,所以要記錄任務(wù)是添加到哪個(gè)結(jié)點(diǎn)上的,需要為每個(gè)樹結(jié)點(diǎn)添加一個(gè)作為標(biāo)識(shí)以便于在結(jié)點(diǎn)上添加任務(wù),樹狀結(jié)構(gòu)中每個(gè)結(jié)點(diǎn)的按照樹的先序遍歷將結(jié)點(diǎn)的依次儲(chǔ)存于數(shù)組中。

localStorage實(shí)現(xiàn)本地儲(chǔ)存樹形菜單

最近在寫一個(gè)Todo-list的頁(yè)面,頁(yè)面布局和操作都寫完后,想要用localStorage實(shí)現(xiàn)本地儲(chǔ)存。然而對(duì)儲(chǔ)存數(shù)據(jù)的方法一無(wú)所知,就先去了解了web的數(shù)據(jù)儲(chǔ)存。

數(shù)據(jù)儲(chǔ)存

常用的web的數(shù)據(jù)儲(chǔ)存有cookie和Web Storage儲(chǔ)存機(jī)制。

cookie

cookie是“小型文本文件”,主要用途是辨別用戶身份、保存用戶登錄信息。cooki是由服務(wù)器端生成、儲(chǔ)存在客戶端上的數(shù)據(jù)(通常經(jīng)過(guò)加密)。

Cookie會(huì)被附加在每個(gè)HTTP請(qǐng)求中,所以無(wú)形中增加了流量。

HTTP請(qǐng)求中的Cookie是明文傳遞的,安全性成問(wèn)題。(除非用HTTPS)

Cookie的大小限制在4KB左右。于復(fù)雜的存儲(chǔ)需求來(lái)說(shuō)是不夠用的。

Web Storage

Web Storage定義了兩種儲(chǔ)存數(shù)據(jù)的對(duì)象,localStorage和sessionStorage,它們儲(chǔ)存大小一般為5MB,機(jī)制如下:

sessionStorage由瀏覽器存儲(chǔ)某個(gè)會(huì)話(browsing session)的數(shù)據(jù),數(shù)據(jù)在當(dāng)前會(huì)話下有效,刷新頁(yè)面數(shù)據(jù)依舊存在,但在關(guān)閉頁(yè)面或?yàn)g覽器后被清除。

localStorage由瀏覽器存儲(chǔ)數(shù)據(jù),數(shù)據(jù)沒(méi)有過(guò)期時(shí)間(expiration time),也就是瀏覽器關(guān)閉再重新打開后數(shù)據(jù)仍然存在。

localStorage對(duì)象的操作

在存儲(chǔ)中設(shè)置值:Storage.setItem()
從存儲(chǔ)中獲取值:Storage.getItem()
響應(yīng)存儲(chǔ)的變化:window.addEventListener("storage", function(e){});
刪除數(shù)據(jù)記錄:Storage.removeItem() 接受一個(gè)參數(shù)——你想要移除的數(shù)據(jù)項(xiàng)的鍵,然后會(huì)將對(duì)應(yīng)的數(shù)據(jù)項(xiàng)從域名對(duì)應(yīng)的存儲(chǔ)對(duì)象中移除。Storage.clear() 不接受參數(shù),只是簡(jiǎn)單地清空域名對(duì)應(yīng)的整個(gè)存儲(chǔ)對(duì)象。

樹形菜單的數(shù)據(jù)儲(chǔ)存

在我的todo-list頁(yè)面中,用戶對(duì)樹的操作有:

在樹形菜單上添加、刪除任務(wù)分類

在任務(wù)分類中添加、刪除該分類中的任務(wù)。
也是是說(shuō)用戶的每次操作后都要更新存儲(chǔ)的數(shù)據(jù),以便在刷新頁(yè)面后顯示出用戶操作后更改過(guò)的頁(yè)面。

由于本地儲(chǔ)存只能存字符串?dāng)?shù)據(jù),所以存儲(chǔ)屬性菜單可以用到JSON。用JSON.parse將一個(gè)JavaScript對(duì)象字符串化為JSON,然后整個(gè)存入localStorage來(lái)實(shí)現(xiàn)保存。用JSON.stringify將JSON字符串解析成為一個(gè)JavaScript對(duì)象來(lái)從存儲(chǔ)中獲取值。
那么怎么用對(duì)象存儲(chǔ)樹形菜單呢,我想到了兩個(gè)方式。

方式一

一種是用一個(gè)對(duì)象treeframe存儲(chǔ)樹的結(jié)構(gòu)(所有的任務(wù)分類,不包括分類中的任務(wù))以及樹結(jié)點(diǎn)中的任務(wù),存儲(chǔ)形式如下。一旦對(duì)樹形菜單執(zhí)行任何一項(xiàng)操作,就更新treeframe對(duì)象。

var treeframe = {
    "任務(wù)列表":{
        "使用說(shuō)明":[
            {
                "title":"普通任務(wù)列表",
                "content":"可以設(shè)定任務(wù)的名稱、任務(wù)描述、任務(wù)截止時(shí)間",
                "endTime":"2016-05-20",
                "type":"normal",
            },
            {
                "title":"添加新分類",
                "content":"通過(guò)左側(cè)自定義分類的文件夾圖標(biāo)添加新分類",
                "endTime":"2017-07-20",
                "type":"normal",
            }
        ],
        "今日任務(wù)":{},
        "短期任務(wù)":{
            "7月":{},
            "8月":{},
            "9月":{}
        },
        "長(zhǎng)期任務(wù)":{}
     }
}
方式二

另一種方式是用一個(gè)對(duì)象treeframe存儲(chǔ)樹的結(jié)構(gòu),還有一個(gè)對(duì)象allTasks存儲(chǔ)所有結(jié)點(diǎn)中的任務(wù)。這種方式只需要在添加、刪除任務(wù)分類時(shí)更新樹的結(jié)構(gòu)treeframe;添加、刪除任務(wù)時(shí)更改allTasks。因?yàn)槿蝿?wù)需要添加到樹的結(jié)構(gòu)上,所以要記錄任務(wù)是添加到哪個(gè)結(jié)點(diǎn)上的,需要為每個(gè)樹結(jié)點(diǎn)添加一個(gè)id作為標(biāo)識(shí)以便于在結(jié)點(diǎn)上添加任務(wù),樹狀結(jié)構(gòu)中每個(gè)結(jié)點(diǎn)的id按照樹的先序遍歷將結(jié)點(diǎn)的id依次儲(chǔ)存于數(shù)組treeClassify.list中。為了每一個(gè)新增的結(jié)點(diǎn)的id都不與已存在的id的結(jié)點(diǎn)相同,用一個(gè)計(jì)數(shù)器fatherIdjsq來(lái)記錄可添加的新id。
存儲(chǔ)形式如下:

var treeframe = {
    "任務(wù)列表":{
        "使用說(shuō)明":{},
        "今日任務(wù)":{},
        "短期任務(wù)":{
            "7月":{},
            "8月":{},
            "9月":{}
        },
        "長(zhǎng)期任務(wù)":{}
     }
}

var allTasks = {
    "list" : [    {
                "fatherId":"fatherId1"
                "title":"普通任務(wù)列表",
                "cnode":{"value":"普通任務(wù)列表"},
                "pnode":{"value":"使用說(shuō)明"},
                "content":"可以設(shè)定任務(wù)的名稱、任務(wù)描述、任務(wù)截止時(shí)間",
                "endTime":"2016-05-20",
                "type":"normal",
            },
            {
                "fatherId":"fatherId5"
                "title":"添加新分類",
                "cnode":{"value":"添加新分類"},
                "pnode":{"value":"使用說(shuō)明"},
                "content":"通過(guò)左側(cè)自定義分類的文件夾圖標(biāo)添加新分類",
                "endTime":"2017-07-20",
                "type":"fast",
            }]
};
var treeClassfiy = {"list":["fatherId0","fatherId1","fatherId2","fatherId3","fatherId4","fatherId5","fatherId6","fatherId8","fatherId7"]}
var fatherIdjsq = 9

我覺(jué)得如果最開始寫整個(gè)todo-list時(shí)對(duì)整個(gè)頁(yè)面的功能和操作以及邏輯都理的特別清楚的話,第一種存儲(chǔ)方法一定用起來(lái)更加方便。但是我選了第二種,因?yàn)檫@樣便于我分別對(duì)樹的結(jié)構(gòu)和任務(wù)列表進(jìn)行操作,和我之前寫好的代碼比較容易融合在一起。
所以最終要存儲(chǔ)的數(shù)據(jù)如下:

- 樹狀結(jié)構(gòu)的存儲(chǔ):對(duì)象字面量形式與json的相互轉(zhuǎn)化
- 樹狀結(jié)構(gòu)中每個(gè)結(jié)點(diǎn)的id:按照樹的先序遍歷將結(jié)點(diǎn)的id依次儲(chǔ)存于數(shù)組中
- 所有任務(wù):每一個(gè)任務(wù)存儲(chǔ)于一個(gè)對(duì)象中,所有任務(wù)的對(duì)象組成一個(gè)數(shù)組
- 可以添加的新id
樹形菜單的操作與儲(chǔ)存 1. 刪除任務(wù)分類

更改樹狀結(jié)構(gòu),在界面上刪除這個(gè)分類的后,將這個(gè)分類的id從存儲(chǔ)id的數(shù)組中刪去。

var jsq = 0;                                                      //計(jì)數(shù)器jsq用來(lái)記錄按先序遍歷樹,并將結(jié)點(diǎn)存于數(shù)組時(shí),該結(jié)點(diǎn)在數(shù)組中的位置
preOrder(treedata);                                               //先序遍歷treeframe(treeframe初始儲(chǔ)存于treedata)
function preOrder(treeframe) {
    for(var key in treeframe) {
        if(jsq===fatherIdArr.indexOf(choseDiv.id)) {              //查找到當(dāng)前要?jiǎng)h除的結(jié)點(diǎn)(通過(guò)查看當(dāng)前要?jiǎng)h除結(jié)點(diǎn)的id在儲(chǔ)存結(jié)點(diǎn)id的數(shù)組(treeClassfiy.list)中的位置)
            delete treeframe[key];                                   //通過(guò)detele刪除對(duì)象的屬性來(lái)刪除結(jié)點(diǎn)
            var pos = treeClassifyIdArr.list.indexOf(choseDiv.id);//查找當(dāng)前要?jiǎng)h除的結(jié)點(diǎn)id在儲(chǔ)存結(jié)點(diǎn)id的數(shù)組中(treeClassfiy.list)的位置
            treeClassifyIdArr.list.splice(pos,1);                  //把id從數(shù)組中刪除
            fatherIdArr.splice(jsq, 1);
            break;
        }
        jsq++;
        if(typeof treeframe[key] === "object") {
            preOrder(treeframe[key]);
        }
    }
}
localStorage.setItem("treeframe", JSON.stringify(treedata));      //將更新的treedata存入設(shè)置的值treeframe中
2. 添加任務(wù)分類

每次手動(dòng)添加任務(wù)分類時(shí),樹狀結(jié)構(gòu)會(huì)改變。也就是說(shuō)樹狀結(jié)構(gòu)的改變,意味著樹的結(jié)點(diǎn)增加/刪除了,存儲(chǔ)結(jié)點(diǎn)id的數(shù)組也要改變。
所以要更改樹狀結(jié)構(gòu),為新添的分類設(shè)置一個(gè)新的id,在界面上創(chuàng)建這個(gè)分類的后,將這個(gè)分類的id插入到存儲(chǔ)id的數(shù)組中。

var jsq = 0;
preOrder(treedata);
function preOrder(treeframe) {
    for(var key in treeframe) {
        if(jsq===fatherIdArr.indexOf(choseDiv.id)) {             //找到被選中的結(jié)點(diǎn)
            fatherIdArr.push("fatherId"+fatherIdjsq);            //先在數(shù)組中添加新的id,使新的結(jié)點(diǎn)渲染到頁(yè)面上
            treeframe[key][value] = {};                          //更新樹狀結(jié)構(gòu),添加結(jié)點(diǎn)(為記錄樹的結(jié)構(gòu)的對(duì)象添加屬性)
            preOrder2(treeframe[key]);
            function preOrder2(treeframe) {                      //jsq記錄被選中結(jié)點(diǎn)的的最后一個(gè)子節(jié)點(diǎn)
                for(var key in treeframe) {
                    jsq++;
                    if(typeof treeframe[key] === "object") {
                        preOrder2(treeframe[key]);
                    }
                }
            }
            break;
        }
        jsq++;
        if(typeof treeframe[key] === "object") {
            preOrder(treeframe[key]);
        }
    }
}
localStorage.setItem("treeframe", JSON.stringify(treedata));     //將更新的treedata存入設(shè)置的值treeframe中
/*此處渲染頁(yè)面*/ 
fatherIdArr.pop();                                               //新的結(jié)點(diǎn)渲染到頁(yè)面上后刪除該結(jié)點(diǎn)的id
fatherIdArr.splice(jsq, 0, "fatherId"+fatherIdjsq++);            //更新該結(jié)點(diǎn)id在id數(shù)組中的位置
treeClassifyIdArr.list = [];                                     //將id數(shù)組中的元素添加到對(duì)象中
for(var j=0;j
3. 刪除任務(wù)
tasklistArr.splice(i,1);
allTasks.list = [];
for(var j=0;j
4. 添加任務(wù)
allTasks.list = [];
for(var i=0;i
5. 測(cè)試本地存儲(chǔ)是否已被填充
if(!localStorage.getItem("treeClassify")) {
//本地沒(méi)有存儲(chǔ),加載初始設(shè)置的頁(yè)面
} else {
//本地有存儲(chǔ),不加載初始設(shè)置的頁(yè)面,而是根據(jù)儲(chǔ)存來(lái)渲染頁(yè)面
}
所有存儲(chǔ)操作的封裝
var Storage = (function(mod) {
    // 刪除、添加、編輯快速任務(wù)和普通任務(wù)的存儲(chǔ)
    mod.TaskChange = function() {
        allTasks.list = [];
        for(var i=0;i
需要注意的地方

加載初始設(shè)置的頁(yè)面的過(guò)程中,不需要存儲(chǔ)任何數(shù)據(jù),也就是不需要操作localStorage對(duì)象。這樣的話如果用戶不對(duì)頁(yè)面進(jìn)行操作,就沒(méi)有任何數(shù)據(jù)需要存儲(chǔ)。只有在用戶對(duì)頁(yè)面進(jìn)行操作后,才會(huì)儲(chǔ)存并再頁(yè)面再次刷新時(shí)按照儲(chǔ)存的內(nèi)容進(jìn)行頁(yè)面的渲染。

在線查看demo

在線demo可供參考,歡迎review代碼,求批評(píng)、建議和交流:p
localStorage實(shí)現(xiàn)本地儲(chǔ)存樹形菜單_demo

參考資料

詳說(shuō) Cookie, LocalStorage 與 SessionStorage
JSON.stringify
鏈?zhǔn)褂?Web Storage API

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/86455.html

相關(guān)文章

  • 前端面試之htm5新特性

    摘要:今天來(lái)談?wù)勄岸嗣嬖囍谢旧厦看我幻娴臅r(shí)候都會(huì)被問(wèn)到的一個(gè)問(wèn)題,那就是的新特性。新表單元素元素,表示電話號(hào)碼。和通過(guò)設(shè)置和特性,可以將輸入框的數(shù)值輸入范圍限定在最低值和最高值之間。一旦為某輸入型控件設(shè)置了特性,那么此項(xiàng)必填,否則無(wú)法提交表單。 今天來(lái)談?wù)勄岸嗣嬖囍谢旧厦看我幻娴臅r(shí)候都會(huì)被問(wèn)到的一個(gè)問(wèn)題,那就是html5的新特性。這個(gè)是學(xué)習(xí)前端必須掌握的基礎(chǔ)知識(shí)。 新增的元素 html5...

    teren 評(píng)論0 收藏0
  • htm5新特性(轉(zhuǎn))

    摘要:轉(zhuǎn)自今天來(lái)談?wù)勄岸嗣嬖囍谢旧厦看我幻娑紩?huì)被問(wèn)到的一個(gè)問(wèn)題,那就是的新特性了。元素,表示生成密匙。和通過(guò)設(shè)置和特性,可以將輸入框的數(shù)值輸入范圍限定在最低值和最高值之間。一旦為某輸入型控件設(shè)置了特性,那么此項(xiàng)必填,否則無(wú)法提交表單。 轉(zhuǎn)自:http://hyuhan.com/2017/07/06/... 今天來(lái)談?wù)勄岸嗣嬖囍谢旧厦看我幻娑紩?huì)被問(wèn)到的一個(gè)問(wèn)題,那就是html5的新特性了。...

    focusj 評(píng)論0 收藏0
  • Chrome擴(kuò)展程序開發(fā)

    摘要:這一步可以參考應(yīng)用商店上傳擴(kuò)展程序一文最后終于搞定,線上可見(jiàn)學(xué)習(xí)資源建立擴(kuò)展程序插件開發(fā)攻略如何成為一名應(yīng)用開發(fā)者擴(kuò)展的開發(fā)下一步插件功能豐富化插件可在網(wǎng)頁(yè)上高亮展示標(biāo)記的文本用重構(gòu)需要使用框架嗎注本文源碼位于倉(cāng)庫(kù),線上產(chǎn)品見(jiàn)和 十一在家無(wú)聊時(shí)開發(fā)了這個(gè)項(xiàng)目。其出發(fā)點(diǎn)是想通過(guò)chrome插件,來(lái)保存網(wǎng)頁(yè)上選中的文本。后來(lái)就順手把前后端都做了(Koa2 + React): chrome...

    dinfer 評(píng)論0 收藏0
  • 利用localStorage本地儲(chǔ)存js文件

    摘要:通過(guò)采用同步的形式獲取內(nèi)容,取得內(nèi)容后,執(zhí)行文件的內(nèi)容,設(shè)置保存到中,再刪除中上個(gè)版本的文件。同步獲取文件內(nèi)容。 利用localStorage儲(chǔ)存js文件,只有在第一次訪問(wèn)該頁(yè)面的時(shí)候加載js文件,以后在訪問(wèn)的時(shí)候加載本地localStorage執(zhí)行 封裝lsFile類 有url、filename(key前綴)、lname(key)、filetext(值)屬性 var lstora...

    haitiancoder 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<