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 的变动。