• 使用原生 cookieStore 方法,让 Cookie 操作更简单


    前言

    对于前端来讲,我们在操作cookie时往往都是基于document.cookie,但它有一个缺点就是操作复杂,它并没有像localStorage那样提供一些getset等方法供我们使用。对与cookie的操作一切都是基于字符串来进行的。为了让cookie的操作更简便, Chrome87率先引入了cookieStore方法。

    document.cookie

    document.cookie可以获取并设置当前文档关联的cookie

    获取cookie

    const cookie = document.cookie
    

    在上面的代码中,cookie 被赋值为一个字符串,该字符串包含所有的 Cookie,每条 cookie 以"分号和空格 (; )"分隔 (即, key=value 键值对)。

    但这拿到的是一整个字符串,如果你想获取cookie中的某一个字段,还需要自己处理

    const converter = {
      read: function (value) {
        if (value[0] === '"') {
          value = value.slice(1, -1);
        }
        return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent)
      },
      write: function (value) {
        return encodeURIComponent(value).replace(
          /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,
          decodeURIComponent
        )
      }
    }
    function getCookie (key) {
                
      const cookies = document.cookie ? document.cookie.split('; ') : [];
      const jar = {};
      for (let i = 0; i < cookies.length; i++) {
        const parts = cookies[i].split('=');
        const value = parts.slice(1).join('=');
    
        try {
          const foundKey = decodeURIComponent(parts[0]);
          jar[foundKey] = converter.read(value, foundKey);
    
          if (key === foundKey) {
            break
          }
        } catch (e) {}
      }
      return key ? jar[key] : jar
    }
    console.log(getCookie('name'))  // 前端南玖
    

    比如上面这段代码就是用来获取单个cookie值的

    设置cookie

    document.cookie = `name=前端南玖;`
    

    它的值是一个键值对形式的字符串。需要注意的是,用这个方法一次只能对一个 cookie 进行设置或更新

    比如:

    document.cookie = `age=18; city=shanghai;`
    

    这样只有age能够设置成功

    • 以下可选的 cookie 属性值可以跟在键值对后,用来具体化对 cookie 的设定/更新,使用分号以作分隔:

      • ;path=path (例如 '/', '/mydir') 如果没有定义,默认为当前文档位置的路径。

      • ;domain=domain (例如 'example.com', 'subdomain.example.com') 如果没有定义,默认为当前文档位置的路径的域名部分。与早期规范相反的是,在域名前面加 . 符将会被忽视,因为浏览器也许会拒绝设置这样的 cookie。如果指定了一个域,那么子域也包含在内。

      • ;max-age=max-age-in-seconds (例如一年为 606024*365)

      •   ;expires=date-in-GMTString-format
        

        如果没有定义,cookie 会在对话结束时过期

      • ;secure (cookie 只通过 https 协议传输)

    • cookie 的值字符串可以用encodeURIComponent() (en-US)来保证它不包含任何逗号、分号或空格 (cookie 值中禁止使用这些值).

    function assign (target) {
      for (var i = 1; i < arguments.length; i++) {
        var source = arguments[i];
        for (var key in source) {
          target[key] = source[key];
        }
      }
      return target
    }
    function setCookie (key, value, attributes) {
      if (typeof document === 'undefined') {
        return
      }
    
      attributes = assign({}, { path: '/' }, attributes);
    
      if (typeof attributes.expires === 'number') {
        attributes.expires = new Date(Date.now() + attributes.expires * 864e5);
      }
      if (attributes.expires) {
        attributes.expires = attributes.expires.toUTCString();
      }
    
      key = encodeURIComponent(key)
        .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
        }
        stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
      }
    
      return (document.cookie =
              key + '=' + converter.write(value, key) + stringifiedAttributes)
    }
    
    setCookie('course', 'fe', { expires: 365 })
    

    这里是js-cookie库对setCookie方法的封装

    删除cookie

    function removeCookie (key, attributes) {
      setCookie(
        key,
        '',
        assign({}, attributes, {
          expires: -1
        })
      );
    }
    
    removeCookie('course')
    

    新方法cookieStore

    以上就是通过document.cookie来操作cookie的方法,未封装方法之前操作起来都非常的不方便。现在我们再来了解一下新方法cookieStore,它是一个类似localStorage的全局对象。

    它提供了一些方法可以让我们更加方便的操作cookie

    获取单个cookie

    cookieStore.get(name)
    

    该方法可以获取对应key的单个cookie,并且以promise形式返回对应的值

    async function getCookie (key) {
      const name = await cookieStore.get(key)
      console.log('【name】', name)
    }
    getCookie('name')
    

    当获取的cookie不存在时,则会返回null

    获取所有cookie

    cookieStore.getAll()
    

    该方法可以获取所有匹配的cookie,并且以promise形式返回一个列表

    async function getAllCookies () {
      const cookies = await cookieStore.getAll()
      console.log('【cookies】', cookies)
    }
    getAllCookies()
    

    cookie不存在时,则会返回一个空数组

    设置cookie

    cookieStore.set()
    

    该方法可以设置cookie,并且会返回一个promise状态,表示是否设置成功

    function setCookie (key, value) {
      cookieStore.set(key, value).then(res => {
        console.log('设置成功')
      }).catch(err => {
        console.log('设置失败')
      })
    }
    setCookie('site', 'https://bettersong.github.io/nanjiu/')
    

    如果想要设置更多的属性,比如:过期时间、路径、域名等,可以传入一个对象

    function setCookie (key, value) {
      cookieStore.set({
        name: key,
        value: value,
        path: '/',
        expires: new Date(2024, 2, 1)
      }).then(res => {
        console.log('设置成功')
      }).catch(err => {
        console.log('设置失败')
    
      })
    }
    setCookie('site', 'https://bettersong.github.io/nanjiu/')
    

    删除cookie

    cookieStore.delete(name)
    

    该方法可以用来删除指定的cookie,同样会返回一个promise状态,来表示是否删除成功

    function removeCookie (key) {
      cookieStore.delete(key).then(res => {
        console.log('删除成功')
      }).catch(err => {
        console.log('删除失败')
      })
    }
    removeCookie('site')
    

    需要注意的是:即使删除一个不存在的cookie也会返回删除成功状态

    监听cookie

    cookieStore.addEventListener('change', (event) => {
      console.log(event)
    });
    

    可以通过change事件来监听cookie的变化,无论是通过cookieStore操作的,还是通过document.cookie来操作的都能够监听到。

    该方法的返回值有两个字段比较重要,分别是:changedelete,它们都是数组类型。用来存放改变和删除的cookie信息

    监听修改

    调用set方法时,会触发change事件,修改或设置的cookie会存放在change数组中

    cookieStore.addEventListener('change', (event) => {
      const type = event.changed.length ? 'change' : 'delete';
      const data = (event.changed.length ? event.changed : event.deleted).map((item) => item.name);
    
      console.log(`【${type}】, cookie:${JSON.stringify(data)}`);
    });
    
    function setCookie (key, value) {
      cookieStore.set(key, value).then(res => {
        console.log('设置成功')
      }).catch(err => {
        console.log('设置失败')
      })
    }
    setCookie('site', 'https://bettersong.github.io/nanjiu/')
    

    ⚠️需要注意的是:

    • 通过document.cookie设置或删除cookie时,都是会触发change事件,不会触发delete事件

    • 即使两次设置cookie的namevalue都相同,也会触发change事件

    监听删除

    调用delete方法时,会触发change事件,删除的cookie会存放在delete数组中

    cookieStore.addEventListener('change', (event) => {
      const type = event.changed.length ? 'change' : 'delete';
      const data = (event.changed.length ? event.changed : event.deleted).map((item) => item.name);
    
      console.log(`【${type}】, cookie:${JSON.stringify(data)}`);
    });
    
    function removeCookie (key) {
      cookieStore.delete(key).then(res => {
        console.log('删除成功')
      }).catch(err => {
        console.log('删除失败')
      })
    }
    removeCookie('site')
    

    ⚠️需要注意的是:

    • 如果删除一个不存在的cookie,则不会触发change事件

    兼容性

    在使用该方法时需要注意浏览器的兼容性

    总结

    cookieStore提供的方法比起直接操作document.cookie要简便许多,不仅支持增删改查,还支持通过change事件来监听cookie的变化,但是在使用过程需要注意兼容性问题。

  • 相关阅读:
    Java String.split()方法具有什么功能呢?
    Unity代码通过Package Manager导入包的方法
    【数据结构】【程序填空】赫夫曼编码
    深度学习求解微分方程系列二:PINN求解burger方程
    统计学习方法 支持向量机(上)
    MySQL索引设计原则
    Unity UGUI透明区域点击无效
    云原生 | Kubernetes - Helm - Prometheus 实现资源限制
    记一次生产慢sql索引优化及思考
    Qwt QwtThermo绘制温度计
  • 原文地址:https://www.cnblogs.com/songyao666/p/18037572