vue 页面刷新数据丢失、数据重置、数据缓存、data缓存、vuex缓存

2023-05-16

页面刷新数据丢失

在vue中data、vuex store等都数据都是在内存当中的,页面一旦刷新,这些数据就会丢失(或者说被重置为初始值),在某些时候很影响用户体验。

缓存,恢复

要想使数据刷新不丢失,就得监听页面刷新事件,在刷新前将数据缓存到本地存储,页面刷新后再将数据从本地存储恢复。目前较普遍的做法是类似这样:

//App.vue的created():
 created() {
    //在页面加载从本地读取状态数据并写入vuex
    if (sessionStorage.getItem("store")) {
      this.$store.replaceState(
        Object.assign(
          {},
          this.$store.state,
          JSON.parse(sessionStorage.getItem("store"))
        )
      );
    }

    //页面刷新前将vuex里的状态数据保存到sessionStorage
    window.addEventListener(
    	"beforeunload",()=>{
    	sessionStorage.setItem("store",JSON.stringify(this.$store.state));
    });
  }

这样做是直接将一整个store保存到本地,但是很多时候我们需要保存到本地的只是一些关键性数据,这样做缺少灵活性,而且对于那些并不想放在vuex中的数据极不友好。

改进:dataCache.ts

基于上面将数据缓存到本地存储然后页面加载时恢复的思想,我对上面的方法做了一些改进:


let caches: Record<string, { [index: string]: unknown }> = {};

let isFirst = false;
let baseId = 0;

const generateId = () => baseId++;

export default {
    /**
     * 将data注册进缓存,可指定自定义的id(通常不推荐这样做),可指定需要进行缓存的属性
     * @param data 需要注册的数据对象
     * @param id 为需要注册的数据对象的id,id最好不要是纯数字,并且必须保证id的唯一性
     * @param propertyKeys 指定需要将data的哪些属性进行缓存
     */
    register(data: { [index: string]: unknown }, id?: string, ...propertyKeys: PropertyKey[]): number | string {
        if (id === undefined) {
            id = (generateId()).toString();
        } else {
            const nid = Number(id);
            //字符串的值为数字,为了防止与默认的id生成策略冲突,将其转化成 id+'_'+generateId() 的形式
            if (!isNaN(nid)) {
                id += '_' + generateId();
            }
        }

        const hasId = Reflect.has(caches, id);

        //第一次渲染就id就已经存在,说明提供了重复的id
        if (isFirst && hasId) {
            throw new Error('Duplicate id:\'' + id + '\'');
        }
        //不是首次渲染且id存在,则对data执行属性值的注入 
        else if (hasId) {
            const cache = Reflect.get(caches, id as PropertyKey);

            if (cache instanceof Array) {
                for (let i = 0; i < cache.length; i++) {
                    data[i] = cache[i];
                }
            } else {
                const keys = propertyKeys.length < 1 ? Reflect.ownKeys(cache) : propertyKeys;

                for (const key of keys) {
                    Reflect.set(data, key, Reflect.get(cache, key));
                }
            }
        }

        //将data放进缓存区
        Reflect.set(caches, id, data);

        return id;
    },
    /**
     * 初始化data-caches,在App.vue的created钩子中调用此函数即可
     * @param itemKey 在sessionStorage中存取caches时的key
     */
    init(itemKey: string): void {
        // 页面加载时读取sessionStorage中的数据
        const jsonString = sessionStorage.getItem(itemKey);

        // jsonString为null说明是第一次渲染页面
        if (jsonString === null) {
            isFirst = true;
        } else {
            caches = JSON.parse(jsonString);
        }

        // 监听页面刷新,刷新时将数据保存到sessionStorage
        window.addEventListener("beforeunload", () => {
            sessionStorage.setItem(itemKey, JSON.stringify(caches));
        });
    }
}

用法

第一步:初始化

将上述代码保存到一个文件名为 dataSessionCache.js 的文件里,
然后在App.vue的created钩子中调用 init 函数进行初始化,需要提供一个itemName:

	//App.vue
	import dc from "./ts/dataCache";

    export default {
        created() {
        	/*参数 itemKey 将作为 sessionStorage 进行
        	 getItem、setItem 操作时的 key,需要保证其唯一性.*/
            dc.init('data-caches');
        },
        //others
        ......
    };

第二步:注册

对于vue组件中的数据

对于vue组件中的数据例如data,将需要缓存的数据写到一个对象里面,然后再created钩子中进行注册,例如:

 import dc from "@/js/dataCache.ts";

 export default {
	data: () => ({	
		//need cache
		cached: {
        	num : 134,
        	str: 'str'
        	......
        }
        //other needn't cache
        ......
    }),

	created(){
		//第二个参数是待缓存的数据对象,必须是一个对象或者数组
		sc.register(this.$data.cached);
	}
 };

对于VueX store

对于vuex store中的数据也可以用类似的方法:

//store中:
export default new Vuex.Store({
    state: {
        cached: {
            key: 'data'
        }
        //others
        ......
    },
    //others
    ......
})

//App.vue中
import dsc from "@/js/dataCache.ts";

export default {
	created() {
    	//别忘了init
       dsc.init('data-caches');
       //注册
       dsc.register(this.$store.state.cached);
    },
    //others
    ......
};

缓存对象的非全部属性

register的原型是register(id, obj, ...propertyKeys),第三个参数的作用是指定需要进行缓存的属性,如果propertyKeys为空则会缓存其全部属性。例如,当我们想 在不改变原有代码的情况下 缓存一个单文本组件的部分data时,可以这样写:

export default {
	data: () => ({
            a:1,
            b:'b'
        }),
        
	created() {
		//只缓存属性a
    	dsc.register('this.data,undefined,'a');
    },
    //others
    ......
}

好处

  1. 在页面刷新前后进行数据的保存/恢复工作,性能开销少
  2. 对原有代码仅需少量修改,或者根本不需要修改原有代码
  3. 简单易用,灵活方便,初始化、注册两步就OK,并且可以灵活的指定需要缓存的数据

git仓库

https://gitee.com/szw-yunie/data-session-cache.js

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue 页面刷新数据丢失、数据重置、数据缓存、data缓存、vuex缓存 的相关文章

  • 如何更新 vue.js 2 上输入类型文本中的值?

    我的刀片 Laravel 视图如下
  • Nuxt.js:开始从 vuex 加载指示器

    根据文档 有一种方法可以在组件中手动启动 nuxt 加载指示器 如下所示 export default methods startLoading this root loading start 有没有办法从 vuex 操作切换加载器 我怎样
  • 带 setter 的 mapState

    我想通过分配setter方法mapState 我目前使用一种解决方法 命名我感兴趣的变量 todo 作为临时名称 storetodo 然后在另一个计算变量中引用它todo methods mapMutations clearTodo upd
  • 重新加载 vue-tables-2 (Vuex) 的数据

    Module https github com matfish2 vue tables 2 https github com matfish2 vue tables 2 我正在创建一个 CRUD 应用程序 如何在 vue tables 2
  • Vue.js:vuex 操作中未捕获的承诺

    我了解 vuex actions 返回承诺 但我还没有找到处理错误的理想模式在 vuex 中 我当前的方法是在我的 axios 插件上使用错误拦截器 然后将错误提交到我的 vuex 存储 in 插件 axios js export defa
  • 使用 Vue-router 进行 Firebase 身份验证检查

    问题是 vue router 的 beforeEnter 比 main js 中的 beforeCreate 钩子更早触发 并且有第二个延迟 而在重新加载 vuex 操作后将用户设置为状态 这会导致用户被弹回登录页面 如何延迟 vue ro
  • 如何使用vuex删除一个项目?

    我刚开始学习vuex 无法删除item 我可以直接在组件中删除项目 deleteCar cars id this http delete http localhost 3000 cars cars id then gt this cars
  • vue项目日期处理day.js

    dayjs安装 1 npm 安装 npm install dayjs save 2 项目使用 import dayjs from dayjs ES 2015 dayjs format 使用介绍 1 秒 获取或设置秒 接受0到59的数字 如果
  • 拓展:vue 父组件调用子组件方法ref(且父组件可通过ref调用的方法传值给子组件)

    1 ref被用来给元素或子组件注册引用信息 引用信息将会注册在父组件的 refs对象上 一 ref被用来给元素或子组件注册引用信息 引用信息将会注册在父组件的 refs对象上 div class formBtn fl 111 div div
  • Vuex 存储在 NUXT 中间件中未定义

    我正在练习 NUXT 从教程来看它运行良好 我的在进入NUXT中间件时失败 逻辑是 如果页面重定向到其他页面 它将进入中间件并使用 axios 获取结果 中间件 search js import axios from axios expor
  • 将 vuex 状态与服务器同步的推荐策略

    想象一下这个简单的例子 您有一个 Vue JS 应用程序 用户可以在其中创建任务列表并对它们进行排序 这些列表应由服务器存储在数据库中 假设我们有一个ListComponent它完成了大部分用户体验 我的问题是 我应该使用哪种模式来处理前后
  • Vuex 模块中的 Nuxtjs Axios CORS 错误

    我正在使用 Nuxtjs 和内置 Vuex 模块以及 Nuxtjs 的官方 axios 我试图从本地服务器获取数据 但它总是抛出 CORS 错误 因此 我对 Github 的公共端点进行了 API 调用 但没有成功 仅在控制台中收到 COR
  • Vuex - 绑定助手中的动态命名空间(mapState,...)

    我正在动态注册 vuex 存储模块 store registerModule home grid GridStore 然后在组件中 export default name GridComponent props namespace type
  • Vuex + 打字稿

    我正在将 JavaScript 项目转换为 TypeScript 但是 当我尝试让 Vue 使用 Vuex 时 出现类型错误 import Vue from vue import Vuex from vuex Vue use Vuex 看起
  • 使用 Vue 3 Composition API 创建全局商店

    我正在尝试仅使用 Vue 3 Composition API 创建一个全局商店 到目前为止 我一直在做实验 并且阅读了很多如何使用 Composition API 但知道我不知道如何使用provide和inject 我所知道的是provid
  • Vuex 动作与突变

    在Vuex中 同时拥有 动作 和 变异 的逻辑是什么 我理解组件无法修改状态的逻辑 这看起来很聪明 但是同时具有操作和突变似乎您正在编写一个函数来触发另一个函数 然后更改状态 动作 和 突变 之间有什么区别 它们如何协同工作 而且我很好奇为
  • 从 Vuex 访问提供给 Vue 的实例/服务 (Vue.js 3)

    背景 考虑以下 app js import API from utils API const api new API config app urls api endpoints token app provide api api 根据我在过
  • 扩展语法 (...) 究竟如何与 mapGetters 配合使用?

    每当你想将计算的 getter 与 Vuex 的 mapGetter 帮助器一起使用时 你可以像这样使用它 mapGetters getter1 getter2 etc 我之前见过扩展运算符用于扩展用作函数参数的数组 但不是在方法前面 就像
  • Vuex - “不要在突变处理程序之外改变 vuex 存储状态”

    我正在尝试从 Firestore 初始化我的 Vuex 商店 最后一行代码context commit SET ACTIVITIES acts 是什么造成了错误 我不认为我会直接改变状态 因为我正在使用一个动作 我可能会错过什么 这是我的
  • 如何使用 Vue 路由器从 Vuex 操作进行导航

    我正在使用 Vue 2 x 和 Vuex 2 x 创建一个 Web 应用程序 我正在通过 http 调用从远程位置获取一些信息 我希望如果该调用失败 我应该重定向到其他页面 GET PETS state gt return http get

随机推荐