js-cookie
最近做了一个需要在不同二级域名的两个项目之间进行通知,尝试了 iframe 方式,发现在移动端失败,于是打算通过 cookie 来进行消息通知。所以去找了前端操作 cookie 的库,后来找到 js-cookie 这个库。由于之前操作 cookie 的经历有限,所以特意去阅读了源码并总结。
源码如下:
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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | /*! * JavaScript Cookie v2.2.0 * https://github.com/js-cookie/js-cookie * * Copyright 2006, 2015 Klaus Hartl & Fagner Brack * Released under the MIT license */ ;(function (factory) { // 各种方式的模块定义 var registeredInModuleLoader = false; if (typeof define === 'function' && define.amd) { define(factory); registeredInModuleLoader = true; } if (typeof exports === 'object') { module.exports = factory(); registeredInModuleLoader = true; } if (!registeredInModuleLoader) { var OldCookies = window.Cookies; var api = window.Cookies = factory(); api.noConflict = function () { window.Cookies = OldCookies; return api; }; } }(function () { // 对象拼接方法 function extend () { var i = 0; var result = {}; for (; i < arguments.length; i++) { var attributes = arguments[ i ]; for (var key in attributes) { result[key] = attributes[key]; } } return result; } function init (converter) { function api (key, value, attributes) { var result; if (typeof document === 'undefined') { return; } // Write 当参数大于 1 的时候认为是 write 操作 if (arguments.length > 1) { // 拼接参数及默认参数 attributes = extend({ path: '/' }, api.defaults, attributes); // 设置过期时间, attributes.expires 是一个数字,代表过期天数 if (typeof attributes.expires === 'number') { var expires = new Date(); // 获取当前时间,在加上 attributes.expires 的天数 864e+5 是一天的毫秒数 expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); attributes.expires = expires; } // We're using "expires" because "max-age" is not supported by IE,IE不支持 max-age,所以使用 expires 来设置过期时间 attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; try { result = JSON.stringify(value); // 如果是对象或者数组,转为 JSON if (/^[\{\[]/.test(result)) { value = result; } } catch (e) {} if (!converter.write) { // 对 value 值进行了 encode 同时对其中部分 code 做了 decode 注意 replace 方法用的很高级 value = encodeURIComponent(String(value)) .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); } else { value = converter.write(value, key); } // 对 key 值做了处理 key = encodeURIComponent(String(key)); key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); key = key.replace(/[\(\)]/g, escape); var stringifiedAttributes = ''; // 将传入的 attributes 连接起来 domain=.geekang.org; expries=121314212; http for (var attributeName in attributes) { if (!attributes[attributeName]) { continue; } stringifiedAttributes += '; ' + attributeName; if (attributes[attributeName] === true) { continue; } stringifiedAttributes += '=' + attributes[attributeName]; } // 写入 cookie。这里说明 cookie 写入的方式 key=value; domain=.geekbang.org... console.log(key + '=' + value + stringifiedAttributes) return (document.cookie = key + '=' + value + stringifiedAttributes); } // Read if (!key) { result = {}; } // To prevent the for loop in the first place assign an empty array // in case there are no cookies at all. Also prevents odd result when // calling "get()" var cookies = document.cookie ? document.cookie.split('; ') : []; var rdecode = /(%[0-9A-Z]{2})+/g; var i = 0; for (; i < cookies.length; i++) { var parts = cookies[i].split('='); var cookie = parts.slice(1).join('='); if (!this.json && cookie.charAt(0) === '"') { cookie = cookie.slice(1, -1); } try { var name = parts[0].replace(rdecode, decodeURIComponent); cookie = converter.read ? converter.read(cookie, name) : converter(cookie, name) || cookie.replace(rdecode, decodeURIComponent); if (this.json) { try { cookie = JSON.parse(cookie); } catch (e) {} } if (key === name) { result = cookie; break; } if (!key) { result[name] = cookie; } } catch (e) {} } return result; } api.set = api; api.get = function (key) { return api.call(api, key); }; api.getJSON = function () { return api.apply({ json: true }, [].slice.call(arguments)); }; api.defaults = {}; // remove 直接设置了传入的 key 的 value 位 '',并且设置过期时间为负 api.remove = function (key, attributes) { api(key, '', extend(attributes, { expires: -1 })); }; api.withConverter = init; return api; } return init(function () {}); })); |
结论如下:
- cookie 的读取方式为
document.cookie
。获取到的是所有该域下cookie
key value 的字符串,不同 key value 之间以;
隔开。例如text=1; name=newming; age=25
。注意拿不到expires
path
等信息。然后可以通过字符串分割拿到某一个信息 - cookie 的写入方式为 document.cookie = ‘key=value; expires=time; path=/; ‘。设置的时候为一条一条的设置,可以带上
path
domain
等信息,属性之间同样以;
隔开,如果 value 是对象的活需要转为字符串 - cookie 的删除
docoment.cookie = 'key=; path=/; expires=time'
。注意时间为 UTCString,并且小于当前时间,即直接将某条属性设置过期即可删除