客戶端儲存(cookie,localStorage及sessionStorage)

目錄

1.知識要點及學習目標

2.客戶端儲存方案

2.1服務端儲存

2.1.1服務端文件儲存

2.1.2內存

2.1.3數據庫:mysql、mongoodb、Oracle等等。

2.2客戶端儲存(離線儲存)

2.2.1瀏覽器

3.cookie

3.1koa中cookie的使用

3.1.1儲存cookie的值;

3.1.2獲取cookie的值

3.1.3options常用設置

4.登錄案例

5.客戶端cookie使用方式 ——通過本地cookie實現記錄換膚功能

5.1設置

5.2獲取

5.3封裝

5.3.1設置cookie封裝

5.3.2獲取cookie

5.4幾種皮膚背景色

5.5客戶端操作cookie特點

6.本地緩存Storage——localStorage及sessionStorage使用

6.1設置

6.2獲取

6.3移出指定數據

6.4清空所有數據

7.通過storage來改造換膚功能

8.本地存儲異同

8.1共同點

8.1.1localStorage和sessionStorage和cookie共同點

8.1.2localStorage和sessionStorage共同點

8.2不同點

8.2.1localStorage

8.2.2sessionStorage

8.2.3cookie


1.知識要點及學習目標

知識要點:

  • 在koa中cookie的使用方式
  • 客戶端cookie的使用方式
  • localStorage及sessionStorage使用
  • 各種本地存儲的異同

學習目標:

  • 學會cookie在服務端及客戶端的使用方式
  • 會使用localStorage及sessionStorage做數據的持久化
  • 瞭解各種本地存儲的異同

以登錄音樂系統案例爲例:

  • 登錄頁面:首次需要輸入用戶名和密碼,點擊記住我後,再次進入登陸頁面時不需要再輸入,可直接登錄;
  • 音樂列表頁面:正確登錄後會進入到音樂列表頁面;
  • 換膚功能:可給音樂列表頁面換主題顏色等;
  • 添加功能:可添加音樂到播放列表(持久化存儲);點擊添加後會跳轉到詳細頁
  • 刪除和清空功能:可刪除指定歌曲,可清空所有歌曲列表

2.客戶端儲存方案

2.1服務端儲存

  1. 服務端文件儲存:如node.js的fs模塊
  2. 內存
  3. 數據庫:mysql、mongoodb、Oracle等等。

2.2客戶端儲存(瀏覽器離線儲存)

客戶端儲存即瀏覽器端儲存,當瀏覽器刷新時,數據依然存在。建議客戶端存儲只儲存一些簡單,沒有必要調用數據庫的數據,而大數據量或關鍵數據還是建議通過服務端儲存。具體依需求而定。

3.cookie(前端/後臺皆可用)

cookie是http協議下,服務端或者腳本可以維護客戶端信息的一種方式。可通過後臺也可通過前端js操作cookie。

4.koa中cookie的使用(後臺cookie的使用)

4.1儲存cookie的值;

ctx.cookies.set(name, value, [options])

4.2獲取cookie的值

ctx.cookies.get(name, [options])

4.3options常用設置

  • maxAge 一個數字表示從 Date.now() 得到的毫秒數。過期時間
  • expires cookie 過期的 Date。當前時間+過期時間
  • path cookie 路徑, 默認是'/'。在哪個路徑下cookie起作用
  • domain cookie 域名
  • secure 安全 cookie 設置後只能通過https來傳遞cookie
  • httpOnly 服務器可訪問 cookie, 默認是 true。設置fasle的話,客戶端不能訪問
  • overwrite 一個布爾值,表示是否覆蓋以前設置的同名的 cookie (默認是 false)。如果是 true, 在同一個請求中設置相同名稱的所有 Cookie。

4.5koa中cookie的使用——登錄案例(記住我)

  • 驗證用戶名密碼是否正確;

  • 實現登錄功能,通過記住我實現七天免登錄;

步驟分析:

  1. 搭建koa環境:koa框架,koa-views,koa-static,koa-router;app.use()加載各個模塊;設置模板引擎;async await異步加載登陸頁面;
  2. 登錄及錯誤頁面處理:post請求方式(獲取參數需要使用koa-bodyparser模塊,通過ctx.request.body獲取數據),且form表單信息以name提交;將表單輸入用戶名和密碼與數據庫數據(沒有數據庫模擬寫死數據)進行校驗,校驗通過就跳轉(ctx.redirect("/list"))到音樂列表頁面list.pug,否則跳轉到錯誤頁面error.pug(需要添加相應路由);自定義錯誤頁面,定時器5秒後跳轉(window.location.href)或點擊可直接跳轉(注意pug模板引擎中js代碼的書寫 script.);
  3. 記住我(登錄中cookie的應用):首次登錄時記住cookie登錄狀態,再次登錄時校驗是否是登錄狀態(記住我是否勾選,沒有勾選後臺獲取不到memberMe字段,勾選後ctx.request.body.memberMe需要儲存登錄成功的狀態),ctx.cookies.set("isLogin");用戶名和密碼直接通過isLogin儲存在瀏覽器上可以看到,所以使用md5進行簡單的加密loginState = md5("zs"+"123"),並通過maxAge設置過期時間,ctx.cookies.set("isLogin",loginState,{maxAge:36000*1000*24*7})
  4. 瀏覽器端兩種方式查看cookie:application下的Cookies;也可通過頁面地址欄上“安全”按鈕進行查看
  5. 再次登錄時判斷有沒有過期ctx.cookies.get("isLogin"),過期了需要重新登錄,沒過期判斷和原用戶名和密碼一致就可以直接自動跳轉。
  6. cookies信息會有本地文件存儲相關信息;且當有cookies時任何一次請求都會在頭部信息中帶上cookies信息

登錄記住用戶名密碼完整案例實現:

index.js:

const Koa = require("koa");
const Router = require("koa-router");
const views = require("koa-views");
const static = require("koa-static");
// form表單提交是post請求,必須使用koa-bodyparser獲取數據
const bodyparser = require("koa-bodyparser");
// md5加密登錄信息
const md5 = require("md5");

// node.js通過require後,會自動將json文件中的數據轉換爲對象
const musicData = require("./data/music.json");

const app = new Koa();
const route = new Router();

// 注意引入的模塊都需要通過app.use()將模塊和router進行關聯
app.use(bodyparser());

// 注意模板引擎是在views中設置
app.use(views(__dirname+"/views"),{
    map:{
        html:"pug"
    }
});
app.use(static(__dirname+"/static"));

route.get("/login",async ctx=>{
    // 每次鏈接到登錄頁面時,先檢驗是否有cookie登錄狀態,有則直接跳轉至list頁面
    let loginState = md5("zs"+"8888");
    if(ctx.cookies.get("isLogin") === loginState){
        ctx.redirect("/list");
    }else{
        await ctx.render("login.pug");
    }
});

// 登錄頁面點擊登錄後,校驗cookie信息,成功自動登錄,否則重新登錄
route.post("/checkUser",async ctx=>{
    // 模擬數據庫寫死數據,當用戶名爲zs,密碼爲8888時登錄成功,直接跳轉到list頁面
    if(ctx.request.body.username === "zs" && ctx.request.body.pwd === "8888"){
        // 登錄信息校驗成功後,判斷如果點擊了memberMe則將登錄信息存入到cookie中
        if(ctx.request.body.memberMe === "on"){
            // 通過md5對用戶名密碼進行加密存到cookie中
            let loginState = md5(ctx.request.body.username+ctx.request.body.pwd);
            ctx.cookies.set("isLogin",loginState,{maxAge:36000*1000*24*7});
        }
        ctx.redirect("/list");

    // 登錄失敗跳轉到錯誤頁面
    }else{
        ctx.redirect("/error");
    }
});

// list歌曲列表頁面
route.get("/list",async ctx=>{
    // 渲染list頁面,並且推送歌曲數據
    await ctx.render("list.pug",{
        musicData
    });
});

// error錯誤頁面
route.get("/error",async ctx=>{
    await ctx.render("error.pug");
});

app.use(route.routes());
app.listen("8989");

login.js:

doctype html
html(lang='en')
  head
    meta(charset='UTF-8')
    meta(name='viewport', content='width=device-width, initial-scale=1.0')
    meta(http-equiv='X-UA-Compatible', content='ie=edge')
    link(rel='stylesheet', href='css/login.css')
    title Document
  body
    .loginContainer
      h1 登錄
      form(action='/checkUser', method='post')
        | 姓名:
        input.inputStyle(type='text', name='username')
        br
        | 密碼:
        input.inputStyle(type='password', name='pwd')
        br
        input.loginStyle(type='submit', value='登錄')
        |  |
        input(type='checkbox', name='memberMe')
        | 記住我

 login.css:

.loginContainer{
    margin: 0 auto;
    width: 600px;
    text-align: center;
    padding-top: 20px;
    padding-bottom: 50px;
    border: 1px solid;
}
.loginContainer input{
    margin-bottom: 20px;
}
.loginStyle{
    width: 180px;
    height: 40px;
    background: rgb(50,203,77);
    color: white;
    font-size: 17px;
}
.inputStyle{
    width: 200px;
    height: 30px;
    padding: 5px;
    outline: none;
}

.inputStyle:focus{
    border: 1px solid rgb(50,203,77);
}

error.pug:

<!DOCTYPE html>
html(lang="en")
    head
        meta(charset="UTF-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        meta(http-equiv="X-UA-Compatible", content="ie=edge")
        title 錯誤頁面
    body
        h1 登錄錯誤
        span.val 5
        span 秒之後自動跳轉。。。。。。
        br
        a(href="/login") 點擊直接跳轉
    //- js定時器控制倒計時5秒後自動跳轉
    script.
        let time = 5;
        let timer = setInterval(function(){
            time--;
            //- 如果time倒計時到0自動跳轉
            document.querySelector(".val").innerHTML = time;
            if(time<1){
                window.location.href = "/login";
                clearInterval(timer);
            }
        },1000);

 list.pug:

doctype html
html(lang='en')
  head
    meta(charset='UTF-8')
    meta(name='viewport', content='width=device-width, initial-scale=1.0')
    meta(http-equiv='X-UA-Compatible', content='ie=edge')
    link(rel="stylesheet", href="css/list.css")
    title 音樂列表
  body
    button.changeSkin 換膚
    .singerContainer
      img.headImg(src='img/singer.jpg')
      .singerRight
        span.singerName 薛之謙
        span.singerDetail 外文名:Joker 國籍:中國 出生地:上海 職業:歌手、演員、主持人
        span
          span.titleKey 單曲
          span.titleValue 286
          span.titleKey 專輯
          span.titleValue 15
          span.titleKey MV
          span.titleValue 262
        .mytbn
          span.hotSong 播放熱門歌曲
          span.attention 關注1316.4萬
    .songList
      .hotSongList
        h2 熱門歌曲
      ul.listContainer.grayWord
        li.grayWord
        li 歌曲
        li 專輯
        li 時長
    each item,key in musicData
      //- 通過key的奇偶性控制隔行顯示灰色背景色grayBg,注意多個class且有判斷時的寫法
      ul(class="listContainer"+(key%2===0?" grayBg":""))
        li.grayWord #{key+1}
        li #{item.songName}
        li #{item.album}
        li.grayWord #{item.time}
        span.btnController
          a(href='#')
            img(src='img/play.png')
          img(src='img/add.png')

list.css:

li{
    list-style: none;
}
.singerContainer{
    height: 250px;
    margin-top: 40px;
    margin-bottom: 35px;
    width: 100%;
    display: flex;
    flex-direction: row;
}
.headImg{
    border-radius: 50%;
    width: 250px;
    margin-right: 5%;
    margin-left: 5%;
}
.singerRight{
    width: 60%;
    display: flex;
    flex-direction: column;
}
.singerName{
    font-size: 38px;
    font-weight: 400;
}
.singerContainer span{
    margin-bottom: 10px;
}
.titleKey{
    color: #000000;
    font-size: 18px;
    margin-right: 10px;

}
.titleValue{
    font-size: 24px; 
    margin-right: 15px;
}
.hotSong{
    width:178px;
    height: 38px;
    background: #31c27c;
    border: 1px solid #31c27c;
    text-align: center;
    color: white;
    line-height: 38px;
    display: block;
    float: left;
}
.attention{
    display: block;
    height: 38px;
    line-height: 38px;
    width: 180px;
    float: left;
    border: 1px solid #c9c9c9;
    text-align: center;
    margin-left: 10px;
}
.mytbn{
    margin-top: 20px;
}
.songList{
    margin-left: 5%;
    margin-right: 5%;
}
.listContainer{
    display: flex;
    flex-direction: row;
}
.grayWord{
    color: #999;
}
.listContainer li{
    flex: 5;
    height: 50px;
    line-height: 50px;
    position: relative;
}
.listContainer li:nth-child(1){
    flex: 1;
    height: 50px;
    line-height: 50px;
}
.listContainer li:nth-child(4){
    flex: 1;
}
.btnController{
    position: absolute;
    left: 30%;
    display: none;
}
.btnController img{
    width: 40px;
    margin-left: 10px;
}
.grayBg{
    background: #fbfbfd;
}
.changeSkin{
    width: 100px;
    height: 30px;
    background: rgb(97,190,130);
    color: white;
    font-size: 14px;
}

 5.客戶端cookie使用方式 (前端JS中cookie的使用)——通過本地cookie實現記錄換膚功能

5.1設置

document.cookie="key=value"
  • key和value是包含在一個字符串中
  • 多個key=value使用 ; (分號)分隔

key包含字段:

  • [name] 這個name爲自己取的cookie名稱,同名的值會覆蓋
  • domain 所屬域名
  • path 所屬路徑
  • Expires/Max-Age 到期時間/持續時間 (單位是秒)(注意客戶端cookies過期時間單位是秒,服務器端是毫秒)
  • http-only 是否只作爲http時使用,如果爲true,那麼客戶端能夠在http請求和響應中進行傳輸,但時客戶端瀏覽器不能使用js去讀取或修改

5.2獲取

document.cookie

返回值是當前域名下的所有cookie,並按照某種格式組織的字符串 :key=value;key1=value1;......keyn=valuen

5.3封裝js中設置和獲取cookie方法

5.3.1設置cookie封裝

//設置cookie
function setCookie(name,value,options={}){
    let cookieData = `${name}=${value};`;
    for(let key in options){
        let str = `${key}=${options[key]};`;
        cookieData += str;
    }
    document.cookie = cookieData;
}

5.3.2獲取cookie

//獲取Cookie
function getCookie(name){
    let arr = document.cookie.split("; ");
    for(let i=0;i<arr.length;i++){
        let items = arr[i].split("=");
        if(items[0]==name){
            return items[1];
        }
    }
    return "";
}

5.4幾種皮膚背景色

["white","rgb(204,232,207)", "rgb(200,200,169)", "rgb(114,111,128)"]

5.5客戶端操作cookie特點

  • 瀏覽器會主動存儲接收到的 set-cookie 頭信息的值
  • 有時效性;
  • 可以設置 http-only 屬性爲 true 來禁止客戶端代碼(js)修改該值

5.6list頁面動態渲染頁面及實現換膚功能案例

  1. list頁面動態渲染:引入data.json數據,將數據推送到list.pug文件
  2. 換膚功能:點擊換膚時,修改list頁面背景色ul(class="listContainer"+(key%2===0?" grayBg":""))。window.onload = function(){}。
  3. 換膚功能做本地緩存:ctx.cookies.set()是將cookies信息保存是在服務端;而此處是在js中通過document.cookie = "test=test;Max-Age=3600;",可以設置cookies的各種參數配置(注意客戶端cookies過期時間單位是秒,服務器端是毫秒);document.cookie可以直接獲取cookies值,如果有多個cookie會用"; "隔開
  4. 手動封裝js中設置和獲取cookie的方式

 

6.本地緩存Storage——localStorage及sessionStorage使用

cookies每次發送請求都會在頭部信息中帶上cookies信息到服務端,但是換膚功能這種信息沒必要帶到服務端,服務端也用不到這些信息。針對這種情況就可以使用本地緩存Storage。

localStorage及sessionStorage的API和使用都是一致的。localStorage及sessionStorage沒有過期時間。

6.1設置sessionStorage/localStorage.setItem(key, value)

sessionStorage/localStorage.setItem(key, value) 添加或更新(如果數據項中已存在該key)數據項中指定key的value

6.2獲取sessionStorage/localStorage.getItem(key)

sessionStorage/localStorage.getItem(key) 獲取數據項中指定key對應的value

6.3移出指定數據sessionStorage/localStorage.removeItem(key)

sessionStorage/localStorage.removeItem(key) 刪除數據項中指定key的value

6.4清空所有數據sessionStorage/localStorage.clear()

sessionStorage/localStorage.clear() 清空所有數據項

6.5案例——通過storage來改造換膚功能

設置和獲取時都是用sessionStorage/localStorage即可

 

6.6案例——通過storage實現添加歌曲列表功能

通過storage實現添加歌曲列表功能:

  • 通過stroage來處理本地多開音樂頁面得問題;
  • 實現刪除及刪除所有列表的功能;

步驟分析:

  1. 隔行顯示不同顏色,在ul行內添加樣式,通過key的奇偶性顯示不同顏色
  2. 控制添加按鈕顯示或隱藏(鼠標移入時顯示,移出隱藏);
  3. 點擊添加時顯示詳細頁,利用localStorage解決多次開啓頁面問題(每次點擊添加將數據進行存儲,並且重新開啓頁面window.open(“/detail”))。detail.js將是否打開狀態存到localStorage中,localStorage.setItem("isOpen",true),當頁面關閉時清除開啓狀態,監聽beforeunload事件,當關閉之前先清除開啓狀態。localStorage緩存多個頁面可以共享,所以在list中判斷如果已經開啓就不打開新頁面。
  4. 將添加的歌曲進行儲存:將val對象通過JSON.stringfy(val)傳遞給detail頁面。list頁面點擊添加時將對象存到localStorage中,在detail頁面判斷如果localStorage中沒有這個對象,就進行存儲,有就進行去重(要轉化數據爲json數據JSON.parse())。
  5. detail頁面將localStorage中的緩存的數據進行顯示。根據數據組裝視圖,並將detail中原有的視圖替換即可。pug中.exchange是div的簡寫方式。
  6. 點擊後自動監控localStorage如果有變化自動更新視圖
  7. 刪除和清空列表(刪除和清空的是localStorage中的數據):注意此處清空所有也不能使用clear,因爲除了對象數據,還有很多其他數據;刪除部分,input框的索引和localStorage中對象索引一致,對應刪除即可,再將刪除後數據寫入到localStorage

 

7.本地存儲異同

7.1共同點

7.1.1localStorage和sessionStorage和cookie共同點

  • 同域(同源策略:基於本域名下)限制:同源策略:請求與響應的 協議、域名、端口都相同 則時同源,否則爲 跨源/跨域
  • 存儲的內容都會轉爲字符串格式:cookie相對小一些,localStorage和sessionStorage相對大一些
  • 都有存儲大小限制

7.1.2localStorage和sessionStorage共同點

  • API相同
  • 存儲大小限制一樣基本類似
  • 無個數限制

7.2不同點

7.2.1localStorage

  • 沒有有效期,除非刪除,否則一直存在
  • 同域下頁面共享(可以跨頁面訪問)
  • 支持 storage 事件

7.2.2sessionStorage

  • 瀏覽器關閉,自動銷燬
  • 頁面私有(不可以跨頁面訪問)
  • 不支持 storage 事件

7.2.3cookie

  • 瀏覽器也會在每次請求的時候主動組織所有域下的cookie到請求頭 cookie 中,發送給服務器端
  • 瀏覽器會主動存儲接收到的 set-cookie 頭信息的值
  • 安全性:可以設置 http-only 屬性爲 true 來禁止客戶端代碼(js)修改該值
  • 可以設置有效期 (默認瀏覽器關閉自動銷燬)(不同瀏覽器有所不同)
  • 同域下個數有限制,最好不要超過50個(不同瀏覽器有所不同)
  • 單個cookie內容大小有限制,最好不要超過4000字節(不同瀏覽器有所不同)

8.項目需求總結

  1. koa框架搭建,路由登錄頁面
  2. 登錄及錯誤頁面處理
  3. cookie記錄登錄狀態實現自動登錄——後臺實現cookie信息保存
  4. 動態渲染list頁面
  5. list頁面(歌曲列表)實現換膚功能——js中實現cookie信息保存,js中cookie實現換膚功能存在的問題
  6. 換膚功能——localStorage實現
  7. list頁面(歌曲列表)顯示隱藏添加按鈕
  8. list頁面(歌曲列表)點擊添加時通過localStorage操作是否顯示detail(詳情頁)
  9. list頁面(歌曲列表)點擊添加後將歌曲信息存儲到localStorage
  10. detail(詳情頁)獲取到localStorage數據,並顯示
  11. 通過localStorage實現detail(詳情頁)刪除和清空歌曲列表

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章