前言
作为一位前端er对cookie一定非常的熟悉,但是在项目中使用到的时候肯定少不了去面向google编程,去找一些cookie的用法,看一些API什么的。如果大家懒得去查一些API和对cookie的封装,一般会用js-cookie,今天就和大家一块学习下js-cookie到底做了什么,通过学习我们一定会收获不少知识的,本文没有什么高大上的技术,都是一些基础知识,相信每个人都能够理解并且用到项目当中去。接下来搬好小板凳,准备发车了。
阅读前准备
1.下载js-cookie到本地
git clone https://github.com/js-cookie/js-cookie.git
cd js-cookie
2.查看官方md文档
首先官方大概介绍一下js-cookie和其优点:一个简单轻量的可以处理cookie的库,任何浏览器都适用,支持各种模块导入方式,还有一些使用方式:可以通过npm下载,也可以通过CDN引入。
常用方法
// 设置cookie值
Cookies.set('name', 'value')
// 设置过期时间 七天后过期
Cookies.set('name', 'value', { expires: 7 })
// 设置过期时间并且只对当前路径有效
Cookies.set('name', 'value', { expires: 7, path: '' })
// 获取设置的cookie
Cookies.get('name')
// 获取所有值
Cookies.get()
// 获某个域名底下的值,如果没有定义,默认为当前文档位置的路径的域名部分
Cookies.get('name', { domain: 'sub.example.com' })
// 删除cookiee
Cookies.remove('name')
cookie常用的参数
-
name 设置或覆盖参数的名字(string)必须
-
value 设置参数值(string)必须
-
path 不填,默认当前文档位置的路径,必须为绝对路径,可选(string | null)
-
domain 不填,默认当前文档位置的路径的域名部分, 可选(string | null)不填,对话结束时过期,设置过期时间,可设置成过去的时间用于删除cookie,可选(Date.toUTCString())
-
secure 可会被https传输, 可选(boolean| null)
-
cookie 存储不太安全可被窃取,将它放在另一个域名或子域名之下,可利用同源策略保护不被读取,可以设置HttpOnly
3.js-cookie源码解析
整体查看方法
首先把js-cookie源码拉取下来
git clone https://github.com/js-cookie/js-cookie.git
打开src文件可以看到三个js
├── api.mjs ├── assign.mjs └── converter.mjs
我们先打开api.mjs, 可以看到引入了其他两个文件, 和有一个init方法,传入了一些默认参数
我们可以先大概了解一下这些方法用来干什么的,init方法我们可以根据名字猜出来进行了初始化,可以看出返回了一个Object.create创建的对象,还有get和set方法我们也可以根据名字猜出来应该分别是设置存入cookie和读取cookie
init函数
我们可以看出init返回了一个新创建的对象
return Object.create(
{
set: set, // 设置cookie方法
get: get, // 读取cookie方法
remove: function (name, attributes) { // 删除cookie方法,其实内部调用了set方法,并把expirse设置为过去时间来删除
set(
name,
'',
assign({}, attributes, {
expires: -1
})
)
},
// 修改设置cookie的一些常用属性类似于path,domain,expires, 重新返回一个实例化的对象,可以设置一个全局的cookie共享设置的一些属性值
withAttributes: function (attributes) {
return init(this.converter, assign({}, this.attributes, attributes))
},
// 和上个方法作用差不多,可以对converter,进行一些扩展
withConverter: function (converter) {
return init(assign({}, this.converter, converter), this.attributes)
}
},
{
// Object.create的可选值,新增一些对象上的属性,
// Object.freeze冻结对象不能删除和修改另外不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值
attributes: { value: Object.freeze(defaultAttributes) },
converter: { value: Object.freeze(converter) }
}
)
set函数
set主要是存储cookie或者通过设置expires来删除cookie
function set (name, value, attributes) {
// 没有document直接return 返回什么也不执行
if (typeof document === 'undefined') {
return
}
// 把传入的值和默认值合并到一起,如果key一样,传入的值直接替换默认值
attributes = assign({}, defaultAttributes, attributes)
// 如果传入expires为天数,时间则直接转换为毫秒
if (typeof attributes.expires === 'number') {
attributes.expires = new Date(Date.now() + attributes.expires * 864e5)
}
// 把日期转为字符串设置cookie过期时间
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) {
// 为空字符串或者null undefined退出本次循环
if (!attributes[attributeName]) {
continue
}
stringifiedAttributes += '; ' + attributeName
// 传入boolean值退出当前循环
if (attributes[attributeName] === true) {
continue
}
stringifiedAttributes += '=' + attributes[attributeName].split(';')[0]
}
// 写入的时候使用converter进行encode编码
return (document.cookie =
name + '=' + converter.write(value, name) + stringifiedAttributes)
}
其关键通过接受传入的name和value值通过document.cookie设置cookie,对传入的其他属性attributes进行了遍历,例如:expires、domain、path,拼接成字符串写入cookie当中, 而且对过期时间进行处理转换,可以使用天数来传入过期时间,另外对name和value进行编码
get函数
get读取存入的cookie,如果没传入值直接返回一个所有存入cookie的对象,也可以使用正则匹配去读取cookie值
function get (name) {
// 判断是否支持cookie
if (typeof document === 'undefined' || (arguments.length && !name)) {
return
}
// 获取到cookie,并把值切割成数组
var cookies = document.cookie ? document.cookie.split('; ') : []
var jar = {}
for (var i = 0; i < cookies.length; i++) {
// 字符串通过'='解析成数组
var parts = cookies[i].split('=')
// 防止vuale存储的时候有等号, 在把name后的所有值拿出来加上等号
var value = parts.slice(1).join('=')
try {
// 解析name
var found = decodeURIComponent(parts[0])
// 通过converter解析value值
jar[found] = converter.read(value, found)
// 找到之后退出本次循环,节省内存
if (name === found) {
break
}
} catch (e) {}
}
// 判断返回单独的一个值还是一个包含所有cookie值的对象
return name ? jar[name] : jar
}
其关键通过接受传入的name读取cookie,对cookie的值进行遍历对比,如果一样直接退出循环并返回值,另外对name和value进行解码
4.总结
js-cookie源码非常简短只有 100 行左右,源码简单易懂,建议自己动手看看。通过学习js-cookie源码自己又重新温故了一遍cookie的API还有Object.create和Object.freeze的API,还有encodeURIComponent和decodeURIComponent方法的使用。