zoukankan      html  css  js  c++  java
  • 浅谈源码之jscookie

    前言

    作为一位前端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方法的使用。

  • 相关阅读:
    第四节 哈希类型
    第三节 string类型
    第二节 redis的数据类型和一些通用的键命令
    第一节 Redis的安装配置
    第三十二节 定时器
    第三十一节 sed命令
    第三十节 awk命令
    第二十九节 cut命令
    第二十八节 函数和脚本调试
    Gartner 如何看 RASP 和 WAF?
  • 原文地址:https://www.cnblogs.com/Limengbo/p/15732455.html
Copyright © 2011-2022 走看看