为了账号安全,请及时绑定邮箱和手机立即绑定

浅谈源码之js-cookie

浅谈源码之js-cookie

图片描述

前言

作为一位前端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常用的参数

  1. name 设置或覆盖参数的名字(string)必须

  2. value 设置参数值(string)必须

  3. path 不填,默认当前文档位置的路径,必须为绝对路径,可选(string | null)

  4. domain 不填,默认当前文档位置的路径的域名部分, 可选(string | null)不填,对话结束时过期,设置过期时间,可设置成过去的时间用于删除cookie,可选(Date.toUTCString())

  5. secure 可会被https传输, 可选(boolean| null)

  6. 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方法的使用。

点击查看更多内容
9人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
87
获赞与收藏
595

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消