Vue3 | 本地存储localstorage、临时存储sessionStorage、js-cookie封装和调用

565 阅读6分钟

需求

  • 把数据保存到本地,读取本地数据

开发

1-多种存储辨析

1-1 localStorage和sessionStorage辨析

  • 共同点:允许在客户端存储一些数据以便在用户会话期间重复使用,而不是每次都需要重新获取
  • 区别:
    • localStorage:持久化的存储方式,一旦你存储了数据,除非用户清除浏览器缓存,否则数据将一直存在。即使浏览器关闭,数据也不会丢失。
    • sessionStorage:会话级别的存储,一旦页面会话结束(如用户关闭了浏览器标签页),存储的数据将被清除。
  • 应用:
    • 用户登录信息:对于需要长期存储的用户认证信息(如用户名、身份验证令牌等),可以使用localStorage。这样,即使用户关闭并重新打开浏览器,登录状态依然保持不变,直到用户登出。
    • 临时数据:对于只需要在当前会话中保持的数据(例如,购物车内容),可以使用sessionStorage。当用户关闭购物车页面或刷新页面时,这些数据将被清除。
    • 状态管理:除了简单的键值对存储外,你还可以使用localStorage或sessionStorage来实现全局状态管理。例如,你可以使用它们来跟踪用户的界面状态或应用程序的其他状态信息。
    • 动态导航菜单:如果你有一个动态导航菜单,可以根据用户的登录状态或其他配置选项来显示或隐藏某些菜单项。通过使用localStorage或sessionStorage,你可以轻松地保存和恢复这些状态。
    • 表单输入:对于需要记住用户输入的表单(如搜索框或地址栏),可以使用localStorage或sessionStorage来存储用户输入的数据,以便在用户刷新页面后自动填充这些字段。
    • 动态主题切换:如果你想让用户能够选择一个主题并记住他们的选择,可以使用localStorage来存储他们的选择。这样,无论用户何时访问你的网站,他们都会看到他们之前选择的主题。
    • 分页或滚动位置:对于长页面或需要记住用户滚动位置的页面,可以使用localStorage或sessionStorage来保存用户的滚动位置,以便在用户返回页面时自动滚动到他们之前的位置。
    • 跨域请求参数:当需要跨域请求参数时,可以使用localStorage来存储这些参数。这样,即使在不同的域名下请求资源,也可以通过访问localStorage中的数据来传递必要的参数。
    • 插件/第三方服务集成:有时你可能需要与第三方服务进行集成,这些服务可能需要访问本地存储的数据。在这种情况下,可以使用localStorage来安全地存储这些敏感信息,并确保只有经过授权的服务才能访问它们。
    • 自定义配置:对于需要在多个组件之间共享的配置信息(例如,UI模式、语言设置等),可以使用localStorage或sessionStorage来存储这些配置,以便在整个应用程序中轻松访问和修改它们。
    • 动态加载资源:对于需要根据用户配置或偏好加载的资源(例如,不同的图像版本、字体等),可以使用localStorage或sessionStorage来跟踪哪些资源已被加载,从而避免重复加载相同的资源。
    • 表单验证结果:在进行表单验证时,可以使用localStorage来保存验证结果(例如,错误消息、成功消息等)。这样可以在表单重新加载时重新显示这些消息,而无需重新进行验证。
    • 缓存请求结果

1-2 localStorage、sessionStorage和Cookie辨析

  • 共同点:用于存储数据
  • 区别:
    • localStorage:仅在客户端存储不参与服务器通信,存储大小一般为5MB。作用域是协议、主机名、端口。如果不是人为清除,那么即使是关闭浏览器也会一直存在。
    • sessionStorage:仅在客户端存储不参与服务器通信,存储大小一般为5MB。作用域是窗口、协议、主机名、端口。会话级存储,也就是说如果关闭当前页面或者浏览器那么就会清除
    • cookie:客户端存储,参与服务器通信,服务器可以通过 HTTP header 操纵存储对象,存储大小为4kB,可设置生命周期,在设置的生命周期内有效

1-3 整理

有效期存储数据大小作用域
localStorage永久5MB协议、主机名、端口
sessionStorage浏览器的会话时间5MB窗口、协议、主机名、端口
cookie可设置4KB

2-LocalStorage和SessionStorage

2-1 LocalStorage:持久的本地存储

  • 场景:登录页面登录成功后会获取用户的信息,登录之后需要显示此用户的信息,可以在请求的时候将用户信息存入浏览器的localstorage中,方便取用
  • 存储数据:
    • localStorage.setItem("name",xxx);,将xxx本地存储为name的变量
    • 注意:存入的数据只能以字符串形式存入
    • localStorage.setItem("name",JSON.stringfy(res.xxx));,将请求返回的对象数据转为JSON格式后存储
  • 读取数据:
    • localStorage.getItem('name');,读取本地存储中名为name的变量
    • JSON.parse(localStorage.getItem("name")),读取JSON格式变量并转为对象格式
  • 移除数据:
    • localStorage.removeItem("name");,移除名为name的变量
    • localStorage.clear();,清空所有本地存储
  • 其他:
    • localStorage是window上的,js中调用window.localStorage.xxxlocalStorage.xxx,而不能是this.localStorage.xxx(指向Vue实例)
    • Chrome查看LocalStorage:image.png
    • 不同浏览器无法共享localStorage
    • 相同浏览器的不同页面间可以共享相同的 localStorage但是前提必须是在同一域名和端口下。如果一个标签页包含多个iframe标签且他们属于同源页面,那么他们之间是可以共享sessionStorage的。
    • 在谷歌无痕模式下,localStorage、cookie是读取不到的,但是你可以新增数据然后读取,但是关闭页面后再打开还是会清空。
    • 在所有同源的窗口之间,localStorage 数据可以共享。因此,如果我们在一个窗口中设置了数据,则在另一个窗口中也可以看到数据变化。
  • 代码:
<script>
export default {
    data() {
        return {
            userInfo: {},
        }
    },
    methods: {
        async handleLogin() {
            const res = await Login();
            if(res.code === 20000) {
                this.userInfo = res.user;       //请求返回的数据是对象
                localStorage.setItem("name",JSON.stringfy(res.user));  //存入的数据是JSON格式
                this.$route.push("/Home"); 
            }
        }
    },
}
</script>
<script>
export default {
    data() {
        return {
            userInfo: {},
        }
    },
    created: {
        getUserInfo() {
            this.userInfo = JSON.parse(localStorage.getItem("name"));
        },
    },
}
</script>

2-2 sessionStorage:会话级别的临时存储

  • 场景:会话级别的存储,这意味着一旦页面会话结束(如用户关闭了浏览器标签页),存储的数据将被清除。因此,你可以将sessionStorage视为一种临时的、在当前浏览器会话中存在的数据存储机制
  • 语法:
    • 存储数据:sessionStorage.setItem('name', xxx);
    • 读取数据:sessionStorage.getItem('name');
    • 删除数据:sessionStorage.removeItem("key");
    • 清空数据:sessionStorage.clear();
  • 查看SessionStorage:image.png
  • 代码:
// 获取文本输入框
let field = document.getElementById("field");


// 检测是否存在 autosave 键值
// (这个会在页面偶然被刷新的情况下存在)
if (sessionStorage.getItem("autosave")) {
  // 恢复文本输入框的内容
  field.value = sessionStorage.getItem("autosave");
}

// 监听文本输入框的 change 事件
field.addEventListener("change", function () {
  // 保存结果到 sessionStorage 对象中
  sessionStorage.setItem("autosave", field.value);
});

2-3 封装Storage

  • 必要性:
    • LocalStorage存储的是字符串,除了number值,其他的都要加双引号。即存储的只能是基本数据类型,引用数据类型没法识别。将引用型加上双引号后可以成功设置。
    • 存储数据时如果键名相同,会覆盖掉前面存储的值,因此需要采用命名空间的方法来进行localStorage的二次封装。
    • 考虑到项目安全,需要限制用户私自修改sessionStorage本地存储

3-Cookie

3-1 安装js-cookie

  • Cookie:
    • cookies和localStrorang的作用一样的,都是用来将数据存储在本地,并且可以设置存储时间
    • cookies的信息会保存在Http请求中,在Web服务器和浏览器之间来回传递;
    • 存储限制:
      • 只能存储文本
      • 存储大小限制:单条数据不大于4KB
      • 存储数量限制:一般50条
      • 读取域名限制:不可跨域读取
      • 存储时效限制:每个cookie都有时效,最短的有效期是会话级别(即浏览器关闭时cookie便销毁)
    • 查看Cookie:image.png
  • js-cookie
    • js-cookie是一个简单的,轻量级的处理cookies的js API
    • 官网:
    • 安装:
      • npm包管理:npm install js-cookie或指定版本npm install js-cookie@2.2.1 --save
      • yarn包管理:yarn add js-cookie或指定版本yarn add js-cookie@2.2.1
      • cnpm包管理:cnpm install js-cookie --save

3-2 封装js-cookie

  • 须知:
    • 引入js-cookie:import Cookies from 'js-cookie'
    • 创建Cookie:
      • Cookies.set('name', 'value');
      • Cookies.set('name', 'value', { expires: 7 });,有效期为7天
      • Cookies.set('name', 'value', { expires: 7, path: '' });,为当前页创建有效期7天
    • 获取Cookie:
      • Cookies.get('name');,获取Cookie的某个变量,如果存在则返回'value',如果不存在返回undefined
      • Cookies.get();,获取所有cookie,返回所有Cookie,如{ name: 'value' }
    • 删除Cookie:
      • Cookies.remove('name');,删除某个变量
      • Cookies.set('name', 'value', { path: '' });,如果设置了路径,删除时需要指定路径:
      • 删除不存在的cookie不会报错也不会有返回
    • 存取json:
      • 存:Cookie.set("books",JSON.stringify(this.booklist)),传入Array或类似对象,而不是简单的string,那么js-cookie会将你传入的数据用JSON.stringify转换为string保存
      • 取:JSON.parse(Cookie.get("books"))
    • 全局挂载(用于高频使用时)
      • 引入:import Cookie from "js-cookie";
      • main.js挂载全局:Vue.prototype.$cookie = Cookie
      • 组件中使用:this.$cookie.set('name', 'value')
  • 代码:
import Cookies from 'js-cookie'
const TokenKey = 'x-access-token'; // 将名称进行了赋值-为了美观
var inFifteenMinutes = new Date(new Date().getTime() + 1200 * 60 * 1000); //设置过期时间
 
// 获取
export function getToken() {
  // console.log('cookies:',Cookies.get('x-access-token'))
    return Cookies.get(TokenKey)
}
 
// 存储
export function setToken(token) {
    // 对应的是(名称,数据,存储时间)
    return Cookies.set(TokenKey, token, { expires: inFifteenMinutes })
}
 
// 删除
export function removeToken() {
    return Cookies.remove(TokenKey) // 根据存储的名称进行删除
}

3-3 调用

  • src/util/auth.js定义:
    • getToken();
    • setToken(token);
    • removeToken();
  • 代码:
<template>
    <p>Login</p>
    <el-form :model="loginForm" :rules="rules" ref="loginForm">
        <el-form-item label="user" prop="user">
            <el-input v-model="loginForm.user" />
        </el-form-item>
        <el-form-item label="password" prop="pw">
            <el-input type="password" v-model="loginForm.pw" @keyup.enter="submit"/>
        </el-form-item>
    </el-form>
    <el-button @click="submit">LOG IN</el-button>
</template>

<script>
import { setToken } from "@/utils/auth";
import { testLogin } from "@/api/user";

export default {
    data() {
        loginForm: [],
        rules: {
            user: [{
                required: true,
                message: "Please input",
                trigger: "blur",
            }],
            pw: [{
                required: true,
                message: "Please input",
                trigger: "blur",
            }],
        }
    },
    methods: {
        async submit() {
            this.$refs.loginForm.validate((valid) => {
                if(valid) {
                    this.loginAjax();
                }
            })
        },
        async loginAjax() {
            const res = await testLogin({...this.loginForm,});
            if(res.code === 20000) {
                this.$message.success("Login Success!");
                const token = res.data.token;
                setToken(token);
                this.$route.push("/");
            }
        }
    }
}
</script>