1. 原生cookie使用
获取cookie(当前位置可访问的)
let allCookie = document.cookie
设置cookie
// 给document.cookie传入一个键值对形式的字符串
document.cookie="name=xxx;"
额外属性
- ;path=path 默认为当前文档位置的路径。(例如 '/', '/mydir'),
- ;domain=domain 默认为当前文档位置的域名。(例如 xxx.com)
- ;max-age=max-age-in-seconds 从文档被访问开始的cookie的存活时间/秒
- ;expires=date-in-GMTString-format 过期时间 注意其格式
Wed, 14 Jun 2017 07:00:00 GMT - ;secure ture/false 如果为true则只通过 https 协议传输
注意:如果max-age和expires同时存在 max-age生效,如果两个都不存在那么当前cookie在当前会话时间内生效
2. 使用js-cookie库
Cookies.set('name', 'value', { expires: 7, path: '' })
Cookies.get('name') // => 'value'
Cookies.get('nothing') // => undefined
Cookies.remove('name')
...
把js-cookie源码拉下来 src/api.mjs src/assign.mjs src/converter.mjs
- 这里有一个.mjs 结尾的文件,表示文件使用es模块 还有一个.cjs结尾的文件,表示文件使用commonjs模块....
主要关注src/api.mjs 可以看到有三个方法 set、get、remove;这就是核心
set方法
function set (name, value, attributes) {
if (typeof document === 'undefined') {
return
}
// 整合传进来的参数 如果属性名相同则覆盖default
attributes = assign({}, defaultAttributes, attributes)
// attributes = {path: '/'}
// 传入的时间 转化成时间戳
if (typeof attributes.expires === 'number') {
attributes.expires = new Date(Date.now() + attributes.expires * 864e5)
}
// 时间戳转化成 Wed, 14 Jun 2017 07:00:00 GMT 这种格式的数据
if (attributes.expires) {
attributes.expires = attributes.expires.toUTCString()
}
// 这边我没有过度关注 只知道他是一个编码过程
name = encodeURIComponent(name)
.replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)
.replace(/[()]/g, escape)
var stringifiedAttributes = ''
for (var attributeName in attributes) {
if (!attributes[attributeName]) {
continue
}
stringifiedAttributes += '; ' + attributeName
if (attributes[attributeName] === true) {
continue
}
// Considers RFC 6265 section 5.2:
// ...
// 3. If the remaining unparsed-attributes contains a %x3B (";")
// character:
// Consume the characters of the unparsed-attributes up to,
// not including, the first %x3B (";") character.
// ...
// ;path=/ ...
stringifiedAttributes += '=' + attributes[attributeName].split(';')[0]
}
// 这边set了cookie 并且返回了它
return (document.cookie =
name + '=' + converter.write(value, name) + stringifiedAttributes)
}
get方法
function get (name) {
if (typeof document === 'undefined' || (arguments.length && !name)) {
return
}
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all.
// yong; 分割字符串 返回数组
// 例: name=xx=123; age=12 => [name=xx,age=12]
var cookies = document.cookie ? document.cookie.split('; ') : []
// 创建一个空对象来存储最后的结果
var jar = {}
for (var i = 0; i < cookies.length; i++) {
var parts = cookies[i].split('=') // parts [name, xx]
var value = parts.slice(1).join('=') // xx
// 这一步还有一个作用 如果value中有=号 比如 name=xxx=123 那么parts就是[name,xxx,123] 这边就会把xxx和123结合起来 =》 value为xxx=123
try {
// 对parts[0]decode
var found = decodeURIComponent(parts[0])
// 组成对象 =》 {name:xxx=123}
jar[found] = converter.read(value, found)
// 如果name === found 也就是找到了传入name对应的value
if (name === found) {
break
}
} catch (e) {}
}
// 找到了就返回jar[name] 没有就返回空对象
return name ? jar[name] : jar
}
remove方法
remove() 方法就是把对应name的expires属性设置为过期时间
remove: function (name, attributes) {
set(
name,
'',
assign({}, attributes, {
expires: -1
})
)
},
withAttributes 方法
withAttributes: function (attributes) {
return init(this.converter, assign({}, this.attributes, attributes))
},
assign({}, this.attributes, attributes) 整合了一下attributes,然后调用init方法 这里为啥要调用init方法呢 如果调用init方法创建一个实例 那么自定义的参数就会影响所有的已经存在的实例!这样不被允许。所有调用init方法创建了一个新的实例 不会影响别人
withConverter 方法同理
attributes、converter
{
attributes: { value: Object.freeze(defaultAttributes) },
converter: { value: Object.freeze(converter) } // 这里把这两个对象冻结,防止被修改
}
3. 简单实现
功能
- set功能
- get功能
- del功能
- 配置注册中心部分
- 冻结配置
总结
用 init 函数创建对象,对象里有以下函数
get 函数:将 document.cookie 字符串转化为 Object 形式,转化过程中判断是否在存 key,如果有就返回对应 value set 函数:把 attributes stringify,然后追加到 key=value 后, document.cookie = {value}${attrStr} del 函数:调用 set,把 expires 设置为 -1 天,cookie 直接过期被删除 withAttributes:更新 attributes 配置,并返回全新 Cookie 对象 withConverter:更新 converter 配置,并返回全新 Cookie 对象 为什么要用函数生成对象这么麻烦?因为要解决全局污染的问题。需要把 attributes 和 converter 两个配置存到函数参数里,并且通过 withAttributes 和 withConverter 调用 init 返回新 Cookie 对象。 为什么要冻动 attributes 和 converter。
我的实现:my-js-cookie