乐趣区

关于前端:一个操作-cookie-的原生方法-cookieStore

TNTWeb – 全称腾讯新闻前端团队,组内小伙伴在 Web 前端、NodeJS 开发、UI 设计、挪动 APP 等大前端畛域都有所实际和积攒。

目前团队次要反对腾讯新闻各业务的前端开发,业务开发之余也积攒积淀了一些前端基础设施,赋能业务提效和产品翻新。

团队提倡开源共建,领有各种技术大牛,团队 Github 地址:https://github.com/tnfe

本文作者 wenzi0github

咱们平时对 cookie 的增删改查等操作,都是在操作 document.cookie,这里咱们介绍一个新办法cookieStore

1. 平时如何操作 cookie

document.cookie 能获取到以后域所有的 cookie 字符串。每个 cookie 用分号进行隔开:

document.cookie; // "a=1; b=2; c=wenzi"

操作 cookie,均是在操作 document.cookie。如上面就是我罕用的一段代码:

/**
 * 写 cookies
 * @param {string} name 写 cookie 的 key
 * @param {string|number} value 写 cookie 的值
 * @param {number} day 存储的工夫,默认 30 天
 */
export const setCookie = (name: string, value: string | number, day = 30): void => {const exp = new Date();
  exp.setTime(exp.getTime() + day * 24 * 60 * 60 * 1000);
  document.cookie = `${name}=${escape(value.toString())};path=/;expires=${exp.toUTCString()}`;
};

/**
 * 读取 cookies
 * @param {string} name 要获取的 cookie 名称
 * @param {number|boolean} type 是否间接获取对应的值,若存入真值,则间接返回,否则进行解码
 */
export const getCookie = (name: string): string | null => {const reg = new RegExp(`(^|)${name}=([^;]*)(;|$)`);
  const arr = document.cookie.match(reg);
  if (arr) {return unescape(arr[2]);
  }
  return null;
};

/**
 * 删除 cookie
 * @param name 删除的 cookie 名称
 */
export const delCookie = (name: string) => {if (!name) return;
  const ex: Date = new Date();
  ex.setTime(ex.getTime() - 1);
  document.cookie = `${name}=; expires=${ex.toUTCString()};path=/`;
};

能够看到设置、获取和删除 cookie,都是在 document.cookie 上进行操作的。

2. 新形式 cookieStore

当初 Chrome 有了更不便操作 cookie 的办法了cookieStore,这个办法是在 Chrome87 版本退出的,兼容性还不太好。

下图是以后日期 2021/03/15 的兼容性概览,能够发现仅仅是 Chrome 体系反对了 cookieStore。

不过咱们能够先来理解它的用法。

cookieStore 当初只能在 https 协定 下的域名能力拜访的到;其余 http 协定的域名里会提醒 cookieStore 为 undefined,或者设置失败。

2.1 根本办法

cookieStore 是一个相似 localStorage 的 object 类型变量。

能够看到 cookieStore 次要有 5 个办法:

  • set: 设置 cookie,能够是 set(name, value),也能够是 set({name, value});
  • get: 获取 cookie,能够是 get(name),或者 get({name});
  • getAll: 获取所有的 cookie;
  • delete: 删除 cookie;
  • onchange: 监听 cookie 的变动;

前 4 个办法人造反对 Promise。接下来咱们一个个来理解下。

2.2 设置 cookie

cookieStore.set 办法能够设置 cookie,并返回一个 Promise 状态,示意是否设置胜利。

cookieStore
  .set('username', 'wenzi')
  .then(() => console.log('设置 username 胜利'))
  .catch(() => console.error('设置 username 失败'));

如果咱们想要设置更多的属性,例如过期工夫,能够传入一个 Object 类型:

cookieStore
  .set({
    name: 'age',
    value: 18,
    expires: new Date().getTime() + 24 * 60 * 60 * 1000,
  })
  .then(() => console.log('设置 age 胜利'))
  .catch(() => console.error('设置 age 失败'));

value 中所有的数据都会默认先执行toString(),而后再进行存储,因而有些非根本类型的数据,最好先转换好。

下面都是咱们设置 cookie 胜利的状况,那么什么时候会设置失败呢?在本地 localhost 环境会设置失败。

本地 localhost,咱们是能获取到 cookieStore 这个全局变量,也能执行相应的办法,但无奈设置胜利:

cookieStore.set('username', 'wenzi');

浏览器会收回提醒,无奈在不平安的域名下通过 CookieStore 中的 set 设置 cookie:

Uncaught (in promise) TypeError: Failed to execute 'set' on 'CookieStore': Cannot modify a secure cookie on insecure origin

增加 catch 后,就能捕捉到这个谬误:

cookieStore
  .set('username', 'wenzi')
  .then(() => console.log('设置 username 胜利'))
  .catch(() => console.error('设置 username 失败'));

因而在想应用 cookieStore 时,不能间接通过上面的形式判断,还得新增一个页面 url 的协定来判断:

typeof cookieStore === 'object'; // 判断不精确,本地 localhost 也会存在

该当应用:

const isSupportCookieStore = typeof cookieStore === 'object' && location.protocol === 'https:'; // 只有在 https 协定下才应用 cookieStore

2.3 获取 cookie

cookieStore.get(name)办法能够获取 name 对应的 cookie,会以 Promise 格局返回所有的属性:

await cookieStore.get('username');

get()办法还能够接管一个 Object 类型,测试后发现,key 的值只能是 name:

await cookieStore.get({name: 'username'});

当获取的 cookie 不存在时,则返回一个 Promise<null>

2.4 获取所有的 cookie

cookieStore.getAll()办法能够获取以后所有的 cookie,以 Promise<[]> 的模式返回的模式返回,数组中的每一项与通过 get()形式获取到的格局一样;若以后域没有 cookie,或者获取不到指定的 cookie,则为空数组;

await cookieStore.getAll();

getAll()办法也能够传入一个 name,用来获取对应的 cookie:

await cookieStore.getAll('username');
await cookieStore.getAll({name: 'username'});

2.5 删除 cookie

cookieStore.delete(name)用来删除指定的 cookie:

cookieStore
  .delete('age')
  .then(() => console.log('删除 age 胜利'))
  .catch(() => console.error('删除 age 失败'));

删除胜利后则会提醒删除胜利。

即便删除一个不存在的 cookie,也会提醒删除胜利。因而,当再次执行下面的代码时,还是会失常提醒。

同样的,在 localhost 环境下会提醒删除失败。

2.6 监听 cookie 的变动

咱们能够通过增加 change 事件,来监听 cookie 的变动,无论是通过 cookieStore 操作,还是间接操作 document.cookie,都能监听。

增加监听事件:

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)}`);
});

这外面有 2 个重要的字段 changed 数组和 deleted 数组,当设置 cookie 时,则 changed 数组里为方才设置的 cookie;当删除 cookie 时,则 deleted 数组里为方才删除的 cookie。

2.6.1 设置操作

当调用 set()办法时,会触发 change 事件,同时影响的 cookie 会放在 event.changed 数组中。

通过 document.cookie 设置或者删除的 cookie,均认为是在批改 cookie,而不是删除。

每次设置 cookie 时,即便两次的 name 和 value 齐全一样,也会触发 change 事件。

cookieStore.set('math', 90);

2.6.2 删除操作

通过 delete()办法删除一个存在的 cookie 时,会触发 change 事件,被删除的 cookie 会放在 event.deleted 数组中。

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

cookieStore.delete('math');

能够看到,当第二次删除 name 为 math 的 cookie 时,就没有触发 change 事件。

3. 总结

咱们整篇理解了下 cookieStore 的应用和操作,要比咱们间接操作 cookie 简便的多,而且还能够通过本身的 change 事件来监听 cookie 的变动。

退出移动版