1. 程式人生 > >4關於Cookie的原理、作用,區別以及使用

4關於Cookie的原理、作用,區別以及使用

1、cookie的作用:

我們在瀏覽器中,經常涉及到資料的交換,比如你登入郵箱,登入一個頁面。我們經常會在此時設定30天內記住我,或者自動登入選項。那麼它們是怎麼記錄資訊的呢,答案就是今天的主角cookie了,Cookie是由HTTP伺服器設定的,儲存在瀏覽器中,但HTTP協議是一種無狀態協議,在資料交換完畢後,伺服器端和客戶端的連結就會關閉,每次交換資料都需要建立新的連結。就像我們去超市買東西,沒有積分卡的情況下,我們買完東西之後,超市沒有我們的任何消費資訊,但我們辦了積分卡之後,超市就有了我們的消費資訊。cookie就像是積分卡,可以儲存積分,商品就是我們的資訊,超市的系統就像伺服器後臺,http協議就是交易的過程。

2、機制的區別:

session機制採用的是在伺服器端保持狀態的方案,而cookie機制則是在客戶端保持狀態的方案,cookie又叫會話跟蹤機制。開啟一次瀏覽器到關閉瀏覽器算是一次會話。說到這裡,講下HTTP協議,前面提到,HTTP協議是一種無狀態協議,在資料交換完畢後,伺服器端和客戶端的連結就會關閉,每次交換資料都需要建立新的連結。此時,伺服器無法從連結上跟蹤會話。cookie可以跟蹤會話,彌補HTTP無狀態協議的不足。

3、cookie的分類:

cookie分為會話cookie和持久cookie,會話cookie是指在不設定它的生命週期expires時的狀態,前面說了,瀏覽器的開啟到關閉就是一次會話,當關閉瀏覽器時,會話cookie就會跟隨瀏覽器而銷燬。當關閉一個頁面時,不影響會話cookie的銷燬。會話cookie就像我們沒有辦理積分卡時,單一的買賣過程,離開之後,資訊則銷燬。

持久cookie則是設定了它的生命週期expires,此時,cookie像商品一樣,有個保質期,關閉瀏覽器之後,它不會銷燬,直到設定的過期時間。對於持久cookie,可以在同一個瀏覽器中傳遞資料,比如,你在開啟一個淘寶頁面登陸後,你在點開一個商品頁面,依然是登入狀態,即便你關閉了瀏覽器,再次開啟瀏覽器,依然會是登入狀態。這就是因為cookie自動將資料傳送到伺服器端,在反饋回來的結果。持久cookie就像是我們辦理了一張積分卡,即便離開,資訊一直保留,直到時間到期,資訊銷燬。


4、簡單的使用cookie的程式碼

cookie的幾種常見屬性:document.cookie="key=value;expires=失效時間;path=路徑;domain=域名;secure;(secure表安全級別),

cookie以字串的形式儲存在瀏覽器中。下面貼段程式碼出來,是一個類似購物網站的將商品新增到購物車,再從購物車還原商品資訊的過程,是自己用原生JS封裝的函式。

封裝的cookie的存入,讀取以及刪除的函式:(這裡是將資訊以物件的形式存放到cookie中的,會用到JSON的知識)


// key : cookie 名
// value : cookie 值
// options : 可選配置引數
//        options = {
//            expires : 7|new Date(), // 失效時間
//            path : "/", // 路徑
//            domain : "", // 域名
//            secure : true // 安全連線
//        }
function cookie(key, value, options) {
    /* read 讀取 */
    // 如果沒有傳遞 value ,則表示根據 key 讀取 cookie 值
    if (typeof value === "undefined") { // 讀取
        // 獲取當前域下所有的 cookie,儲存到 cookies 陣列中
        var cookies = document.cookie.split("; ");
        // 遍歷 cookies 陣列中的每個元素
        for (var i = 0, len = cookies.length; i < len; i++) {
            // cookies[i] : 當前遍歷到的元素,代表的是 "key=value" 意思的字串,
            // 將字串以 = 號分割返回的陣列中第一個元素表示 key,
            // 第二個元素表示 value
            var cookie = cookies[i].split("=");
            // 判斷是否是要查詢的 key,對查詢的 key 、value 都要做解碼操作
            if (decodeURIComponent(cookie[0]) === key) {
                return decodeURIComponent(cookie[1]);
            }
        }
        // 沒有查詢到指定的 key 對應的 value 值,則返回 null
        return null;
    }
 
    /* 存入 設定 */
    // 設定 options 預設為空物件
    options = options || {};
    // key = value,物件 key,value 編碼
    var cookie = encodeURIComponent(key) + "=" + encodeURIComponent(value);
    // 失效時間
    if ((typeof options.expires) !== "undefined") { // 有配置失效時間
        if (typeof options.expires === "number") { // 失效時間為數字
            var days = options.expires, 
                t = options.expires = new Date();
            t.setDate(t.getDate() + days);
        } 
        cookie += ";expires=" + options.expires.toUTCString();
    }
    // 路徑
    if (typeof options.path !== "undefined")
        cookie += ";path=" + options.path;
    // 域名
    if (typeof options.domain !== "undefined")
        cookie += ";domain=" + options.domain;
    // 安全連線
    if (options.secure)
        cookie += ";secure";
 
    // 儲存
    document.cookie = cookie;
}
 
// 從所有的 cookie 中刪除指定的 cookie
function removeCookie(key, options) {
    options = options || {};
    options.expires = -1; // 將失效時間設定為 1 天前
    cookie(key, "", options);
}

下面是商品詳情頁的JS程式碼

// 找到所有的 “新增到購物車” 超級連結
            var links = $("a", $("#tab"));
            // 迴圈,為每個 “新增到購物車” 的超級連結新增點選事件
            for (var i = 0, len = links.length; i < len; i++) {
                links[i].onclick = function(){
                    // 獲取當前超級連結所在行的所有單元格
                    var _cells = this.parentNode.parentNode.cells;
                    // 獲取到即將新增到購物車中的商品資訊
                    var _id = _cells[0].innerHTML,
                        _name = _cells[1].innerHTML,
                        _price = _cells[2].innerHTML;
                    // 將商品資訊包裝到一個物件中
                    var product = {
                        id : _id,
                        name : _name,
                        price : _price,
                        amount : 1
                    };
 
                    /* 將當前選購的商品物件儲存到 cookie 中去 */
                    // 從 cookie 中讀取已有的儲存購物車的陣列結構
                    var _products = cookie("products");
                    if (_products === null) // cookie 中不存在 products 名的 cookie
                        _products = [];
                    else // 存在,則解析 cookie 讀取到的字串為 陣列 結構
                        _products = JSON.parse(_products);
 
                    // 將當前選購的商品追加到陣列中儲存
                    _products.push(product);
                    // 繼續將 _products 陣列內容存回 cookie
                    cookie("products", JSON.stringify(_products), {expires:7});
                }
            }
html程式碼,css程式碼大家可以自己寫

<table id="tab">
        <tr>
            <td>序號</td>
            <td>名稱</td>
            <td>價格</td>
            <td>操作</td>
        </tr>
        <tr>
            <td>1</td>
            <td>空調</td>
            <td>3999</td>
            <td><a href="javascript:void(0);">新增到購物車</a></td>
        </tr>
        <tr>
            <td>2</td>
            <td>風扇</td>
            <td>288</td>
            <td><a href="javascript:void(0);">新增到購物車</a></td>
        </tr>
    </table>
    <a href="cart_購物車.html" target="_blank">檢視購物車</a>

購物車還原商品資訊:

// 從 cookie 中讀取購物車已有的商品資訊
            var _products = cookie("products");
            // 判斷購物車是否有商品
            if (_products === null || (_products = JSON.parse(_products)).length === 0)
                return;
 
            // 如果有商品,則顯示到頁面中
            $(".result")[0].innerHTML = "";
            for (var i = 0, len = _products.length; i < len; i++) {
                // 當前遍歷到的商品物件
                var prod = _products[i];
                // 克隆 .row 的節點
                var _row = $(".row")[0].cloneNode(true);
                // 將當前商品物件的資訊替換節點中對應的部分,用class名獲取到的節點返回型別是一個數組所以要在後面加上[0]
                $(".index", _row)[0].innerHTML = prod.id; // 編號
                $(".name", _row)[0].innerHTML = prod.name; // 名稱
                $(".price", _row)[0].innerHTML = prod.price; // 價格
                $(".amount", _row)[0].innerHTML = prod.amount; // 數量
                $(".oper", _row)[0].innerHTML = "<a href='javascript:void(0);'>刪除</a>"
 
                // 將克隆的節點副本追加到 .result 的 div 中
                $(".result")[0].appendChild(_row);
            };
 
            // 為每個 “刪除” 的超級連結繫結點選事件
            var links = $("a", $("#container"));
            for (var i = 0, len = links.length; i < len; i++) {
                // links[i].index = i; // 為當前遍歷到的超級連結附加資料
                links[i].product = _products[i]; // 
                links[i].onclick = function(){
                    // alert("你點選的是第" + (this.index + 1) + "個連線");
                    var index = inArray(this.product, _products);
                    
                    if (index !== -1) {
                        _products.splice(index, 1);
                    }
                    // 更新 cookie
                    cookie("products", JSON.stringify(_products), {expires:7});
 
                    // 找出頁面中待刪除的行
                    var _row = this.parentNode.parentNode;
                    _row.parentNode.removeChild(_row);
                };
            }
這裡的$(' ')函式是自己封裝的函式,用於獲取到DOM節點,可以看下我關於getElementsByClassName的相容那篇文章。
購物車的html程式碼


<div id="container">
        <div class="row">
            <div class="index">商品編號</div>
            <div class="name">商品名稱</div>
            <div class="price">價格</div>
            <div class="amount">數量</div>
            <div class="oper">操作</div>
        </div>
        <div class="result" style="clear:both;">
            購物車為空
        </div>
    </div>