再谈浏览器存储之 localStorage 和 cookie

简介: WEB 项目的开发,不可避免的要设计存储,这里所说的主要是浏览器存储。之前在文章《WEB 本地存储:localStorage、Web SQL Database、IndexedDB》介绍过浏览器存储。本文之所有再谈浏览器存储,是希望从更加细致的角度出发,并分享存储相关的方法集合。

WEB 项目的开发,不可避免的要设计存储,这里所说的主要是浏览器存储。之前在文章《WEB 本地存储:localStorage、Web SQL Database、IndexedDB》介绍过浏览器存储。本文之所有再谈浏览器存储,是希望从更加细致的角度出发,并分享存储相关的方法集合。

浏览器存储

在 React 或者 Vue 应用程序中,通常将数据存储在 store 中,要么使用组件状态,要么使用状态管理工具,例如 ReduxVuexMobX 。这些由状态驱动UI的工具很好用,当用户刷新页面时,必须重新通过 API 获取所有的数据并再次填充状态。在很多情况下,可能希望以这样一种方式持久化数据,即当用户刷新页面时,一切都不会丢失。想象一下这样一个场景:用户每次刷新页面时都必须重新进行身份验证!

本文将详细介绍在浏览器中存储数据的常用的方式:localStoragesessionStoragecookies,而关于 IndexedDB 后续将专门详细介绍和使用指南。

浏览器存储概述

  • localStorage:完全存在于客户端(浏览器)中的键/值存储。用于存储不需要发送到服务器的身份验证 Token  或者离线数据。
  • sessionStorage:一种键/值存储,其功能与 localStorage 类似,但在用户关闭页面时过期/清除,即使在同一域中也不会跨选项卡共享,最适用于存储临时数据。
  • cookie:可以在浏览器中读取和写入的数据,但也会随着每个请求的 cookie header 中的传输到服务器。
  • IndexDB:一个存在于浏览器中的数据库,单独使用有点困难,但与 PouchDB 等工具配合使用,可用于存储需要查询和性能要求的更复杂的客户端数据。

localStorage 和 sessionStorage

localStoragesessionStorage 都是使用 Storage 对象的键/值存储,并且键和值都必须是字符串。

// Set值
localStorage.setItem("name", "DevPoint");
// Get值
localStorage.getItem("name"); // "DevPoint"
// Delete值
localStorage.removeItem("name");
// Clear所有的值
localStorage.clear();

前面提到的键和值都必须是字符串,那么如何用于存储数组或对象呢?这时就需要使用 JSON.stringify(object) 将 JS 对象转换为 JSON 字符串,并在获取值的时候使用 JSON.parse(string)JSON 字符串转换回 JS 对象。下面是一个完整的处理方法集:

const useStorage = (storageKey = "authorization") => {
    const localKey = `devpoint.local.${storageKey}`;
    const toJson = (str) => {
        try {
            return JSON.parse(str);
        } catch {
            return str;
        }
    };
    const toStringfy = (value)=>{
        try {
            return JSON.stringify(value);
        } catch {
            return value;
        }
    }
    const save = (data) => {
        window.localStorage.setItem(localKey, JSON.stringify(data));
    };
    const get = () => {
        const localData = window.localStorage.getItem(localKey);
        if (localData && localData !== "") {
            return toJson(localData);
        } else {
            return false;
        }
    };
    /**
     * Delete
     */
    const del = () => {
        window.localStorage.removeItem(localKey);
    };
    /**
     * 清除所有的 localStorage
     */
    const clear = () => {
        window.localStorage.clear();
    };
    // 返回存储对象处理方法
    return {
        save,
        get,
        del,
        clear,
    };
};
const storageAuth = useStorage();
const loginInfo = {
    username: "DevPoint",
    age: 30,
};
storageAuth.save(loginInfo);
console.log(storageAuth.get());

Cookies

HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。是WEB项目开发需要涉及的内容。

如果应用程序是完全客户端 SPA(单页应用程序),可能不需要 cookie,使用 localStorage 可以解决问题。如果是使用 Next.js 或者 Node.js 提供服务器接口需要身份验证 Token 的可以考虑使用  cookie

通常认为 cookie 是复数形式,但事实是它们存储在单个字符串值中,必须对其进行解析才能将它们分解为单独的键/值对

console.log(document.cookie); // _gcl_au=1.1.1660316496.1636468606; _ga=GA1.2.221099298.1636468607; _gid=GA1.2.1474751041.1636468607;

可以通过  ;  拆分字符串来将它们分开,然后映射每个值并使用 = 将其拆分为 ,最终将得到相应的键/值对。下面是一个完整的方法集:

const useCookie = (options = { days: 30, path: "/" }) => {
    const { days: expiresDays, path: cookiePath } = options;
    const set = (name, value) => {
        const exp = new Date();
        exp.setTime(exp.getTime() + expiresDays * 24 * 60 * 60 * 1000);
        const strExpires = exp.toGMTString();
        const cookieValue = escape(value);
        document.cookie = `${name}=${cookieValue};expires=${strExpires};path=${cookiePath}`;
    };
    const get = (name) => {
        let arr;
        const reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
        if ((arr = document.cookie.match(reg))) {
            return unescape(arr[2]);
        } else {
            return null;
        }
    };
    // 删除cookie
    const remove = (name) => {
        document.cookie = name + "=;expires=" + new Date(0).toGMTString();
    };
    // 清除所有 cookie
    const clear = () =>
        document.cookie
            .split(";")
            .forEach(
                (cookie) =>
                    (document.cookie = cookie
                        .replace(/^ +/, "")
                        .replace(
                            /=.*/,
                            `=;expires=${new Date().toUTCString()};path=${cookiePath}}`
                        ))
            );
    /**
     * 获取所有的 cookie
     * @returns
     */
    const all = () =>
        document.cookie
            .split(";")
            .map((item) => item.split("="))
            .reduce(
                (acc, [k, v]) => (acc[k.trim().replace('"', "")] = v) && acc,
                {}
            );
    return {
        set,
        get,
        clear,
        remove,
        all,
    };
};
const cookieHelper = useCookie();
cookieHelper.set("name", "DevPoint");
cookieHelper.set("city", "Shenzhen");
console.log(cookieHelper.get("name")); // DevPoint
console.log(cookieHelper.all()); // { name: "DevPoint", city: "Shenzhen" }
cookieHelper.remove("name");
console.log(cookieHelper.all()); // { city: "Shenzhen" }

出于安全考虑,某些 cookie 可能被标记为 仅 HTTP ,这意味着此类 cookie  不能从客户端的 JavaScript 代码中获取到。

存储事件

在上面看到了一些非常简洁的东西,localStorage  和 sessionStorage 还有一个保存或者更新值时进行监听的事件 storage ,然而触发监听事件需要满足一下两个条件:

  1. 通过 localStorage.setItemsessionStorage.setItem 保存(更新)某个storage
  2. 保存(更新)这个 storage 时,它的新值必须与之前的值不同
window.addEventListener("storage", (event) => {
    console.log(event);
});

事件 event 是一个 StorageEvent 对象,

  • oldValue:更新前的值。如果该键为新增加,则这个属性为 null
  • newValue:更新后的值,如果键被删除,则这个属性为 null
  • url:原始触发 storage 事件的页面网址。
  • key:更新的存储键

需要特别注意的是,事件StorageEvent 不会在当前页面触发,只有在浏览器打开同一个域名下的多个页面,其它页面操作改变了 localStoragesessionStorage 的值才被触发。

总结

浏览器存储对于客户端存储数据非常有用,无需调用服务器数据,始终存储在用户浏览器端。


相关文章
|
1月前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
2月前
|
存储 JavaScript 前端开发
vuex和localstorage . cookie的区别
【10月更文挑战第8天】
60 1
|
4月前
|
存储 JavaScript 前端开发
学习vuex和localstorage . cookie的作用与区别
探讨Vuex、LocalStorage与Cookie:三种关键技术在现代Web开发中的角色。Vuex作为Vue的状态管理工具,提供集中、响应式且可预测的状态变更机制,适用于复杂应用。LocalStorage为客户端提供大容量、持久化的数据存储方案,适合保存用户偏好等静态信息。Cookie则擅长会话跟踪与认证管理,数据虽小却能在客户端与服务器间传递。每种技术针对不同场景各有优势,合理选用是关键。
|
2月前
|
存储 缓存 JavaScript
cookie和localStorage的区别特点
cookie和localStorage的区别特点
168 0
|
3月前
|
存储 编解码 JSON
解决浏览器存储问题,不得不了解的cookie、localStorage和sessionStorage
该文章详细对比了浏览器存储机制中的cookie、localStorage和sessionStorage的不同之处,以及各自的适用场景。
|
4月前
|
存储
【Azure APIM】APIM 策略语句如何来设置多个Cookie值让浏览器保存
【Azure APIM】APIM 策略语句如何来设置多个Cookie值让浏览器保存
|
4月前
|
存储 缓存 JavaScript
cookie和localStorage的区别特点
cookie和localStorage的区别特点
54 0
|
5月前
|
存储 前端开发 安全
JavaScript进阶 - 浏览器存储:localStorage, sessionStorage, cookies
【7月更文挑战第2天】探索Web存储:localStorage持久化,sessionStorage会话限定,cookies则伴随HTTP请求。了解它们的特性和限制,如localStorage的5MB容量限制、跨域问题,sessionStorage的生命周期,及cookies的安全与带宽消耗。使用时需权衡安全、效率与应用场景。示例代码展示存储与检索方法。
352 2
|
5月前
|
存储 JavaScript 前端开发
JavaScript进阶 - 浏览器存储:localStorage, sessionStorage, cookies
【7月更文挑战第8天】Web开发中的客户端存储技术,如`localStorage`, `sessionStorage`和`cookies`,用于保存用户设置和跟踪活动。`localStorage`持久化存储,`sessionStorage`随页面会话消失。两者提供基本的增删查改操作,但有大小限制和安全风险。`cookies`适合会话管理,可设置过期时间并能跨域。使用时注意存储量、安全性和跨域策略,选择适合场景的存储方式。
241 0
|
5月前
|
存储 Web App开发 JavaScript
浏览器【详解】Cookie(含Cookie的起源,属性,个数和大小限制,作用,优点,缺点,JS 的操作方法等)
浏览器【详解】Cookie(含Cookie的起源,属性,个数和大小限制,作用,优点,缺点,JS 的操作方法等)
242 0