前端基礎(七):cookie操作

大司馬愛學習發表於2018-07-09

字數:1293

閱讀時間:5分鐘

簡介

cookie語法:

Cookie:

Cookie:name=value;

Cookie:name=value; name1=value1; name2=value2

在使用cookie之前,我們先清晰一個概念:cookie是http請求的請求首部屬性之一,是通過服務端或者指令碼設定的儲存於瀏覽器客戶端中的資訊。如果使用者手動在瀏覽器中設定了禁用cookie,我們就無法使用它了。

它的語法就是一系列的名稱值對用=操作符連線,然後每一對名稱值對之間使用分號+空格隔開。

因瀏覽器同源策略,我們是無法跨域操作cookie的。

我們會用它儲存一些簡單的臨時的資訊,例如登入令牌。

##JS中操作cookie

在JS中,我們可以通過document全域性物件提供的介面來操作cookie。

語法:

let strCookies = document.cookie; //獲取cookie

document.cookie = strCookies; //更新cookie

strCookies的值就是上述的cookie語法形式。不過屬性值後面可以跟上如下配置資料,使用分號為分隔。

-;path=path配置cookie的路徑,預設為當前文件的路徑。document.cookie可以獲取到當前路徑和子路徑的資訊。

-domain=domain配置cookie的域名,預設為當前域。document.cookie無法獲取不同域的資訊。

-max-age=max-age-in-seconds設定當前cookie的保留時間,單位為妙,預設cookie會在當前會話關閉(即瀏覽器關閉)時失效。

-expires=date-in-GMTString-format設定當前cookie保留到哪個時間點,接收GMTString的日期格式資料,預設cookie會在當前會話關閉(即瀏覽器關閉)時失效。

-;secure設定cookie在https時才生效。

這裡,我們要注意一下幾點:

①cookie的值中是不允許出現任何逗號、分號或空格,所以cookie值可以使用encodeURIComponent()來轉換一次。

max-age是在http1.1中用來取代expires出現的新屬性,ie9以下不支援max-age。當同時存在max-age和expires時,會自動忽略掉expires。因此,這裡建議兩個屬性都維護一下。

下面,我們引用MDN中的一個操作cookie的示例為例,嘗試一下cookie的正確操作方式。

var CookieOper = {
    /**
     * 獲取cookie值
     * @param  {String} sKey cookie名稱
     * @return {String}      cookie值
     */
    getItem: function (sKey) {
        if (!sKey) { return null; }
        return decodeURIComponent(document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null;
    },
    /**
     * 設定cookie值
     * @param {String} sKey    cookie名稱
     * @param {String} sValue  cookie值
     * @param {Number|String|Date} vEnd    保留時間
     * @param {String} sPath   路徑
     * @param {String} sDomain 域
     * @param {Boolean} bSecure 是否開啟安全協議
     */
    setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
        if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
        var sExpires = '';
        if (vEnd) {
            switch (vEnd.constructor) {
            case Number:
                sExpires = vEnd === Infinity ? '; expires=Fri, 31 Dec 9999 23:59:59 GMT' : '; max-age=' + vEnd;
                break;
            case String:
                sExpires = '; expires=' + vEnd;
                break;
            case Date:
                sExpires = '; expires=' + vEnd.toUTCString();
                break;
            }
        }
        document.cookie = encodeURIComponent(sKey) + '=' + encodeURIComponent(sValue) + sExpires + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : '') + (bSecure ? '; secure' : '');
        return true;
    },
    /**
     * 刪除cookie
     * @param  {String} sKey    cookie名稱
     * @param  {String} sPath   路徑
     * @param  {String} sDomain 域
     */
    removeItem: function (sKey, sPath, sDomain) {
        if (!this.hasItem(sKey)) { return false; }
        document.cookie = encodeURIComponent(sKey) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : '');
        return true;
    },
    /**
     * 是否擁有對應名稱的cookie
     * @param  {String}  sKey cookie名稱
     * @return {Boolean}      是否擁有cookie
     */
    hasItem: function (sKey) {
        if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
        return (new RegExp('(?:^|;\\s*)' + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=')).test(document.cookie);
    },
    /**
     * 獲取所有cookie名稱
     * @return {Array} 名稱集合
     */
    keys: function () {
        var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, '').split(/\s*(?:\=[^;]*)?;\s*/);
        for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
        return aKeys;
    }
};
複製程式碼

其他的都好理解,需要注意的是,刪除cookie是設定cookie過時即可,並非我們慣性的刪除操作。然後設定cookie的名稱和值的時候注意使用encodeURIComponent方法轉換一下。

使用不同的引數測試介面結果如下:

//document.cookie = "key1=value1"
CookieOper.setItem('key1', 'value1');

//document.cookie = "key1=value1; key2=value2"
//一分鐘到期
CookieOper.setItem('key2', 'value2', 60);

//document.cookie = "key1=value1; key2=value2"
//無法通過 document.cookie 獲取到不同路徑下的cookie資訊,
//但是可以獲取到當前路徑下子目錄的資訊
CookieOper.setItem('key3', 'value3', null, '/dir/');
//刪除失敗
CookieOper.removeItem('key3', '/dir/');

//document.cookie = "key1=value1; key2=value2"
//當前域中的cookie不會變化
//這裡文件的訪問地址為:lp:8020
CookieOper.setItem('key4', 'value4', null, null, '11.lp');

//document.cookie = "key1=value1; key2=value2"
//由於當前地址並沒有使用https,所以cookie設定無法生效。
CookieOper.setItem('key4', 'value4', null, null, null, true);
複製程式碼

注意事項

①由於使用者可以設定禁用cookie,所以在使用cookie時,我們需要考慮到這種情況。

②不要跨域使用cookie。

③對於https協議的網頁,我們需要加上secure引數。

④最好是同時維護好max-age和expires。

⑤設定cookie名稱和值的時候,使用encodeURIComponent函式轉換一下。

參考資料

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cookie

https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie

https://blog.csdn.net/eroswang/article/details/8302191

歡迎關注我的微信公眾號:

前端基礎(七):cookie操作

相關文章