vue page refresh, data loss, data reset, data cache, data cache, vuex cache

Posted by jarriola on Fri, 04 Mar 2022 13:03:15 +0100

Page refresh data lost

In vue, data, vuex store and other data are in memory. Once the page is refreshed, these data will be lost (or reset to the initial value), which will affect the user experience at some times.

Cache, recovery

If you want to make the data refresh not lost, you have to listen to the page refresh event, cache the data to the local storage before the refresh, and then recover the data from the local storage after the page refresh. At present, the more common practice is similar to this:

//App.vue's created():
 created() {
    //Read the status data locally and write it to vuex when loading the page
    if (sessionStorage.getItem("store")) {
      this.$store.replaceState(
        Object.assign(
          {},
          this.$store.state,
          JSON.parse(sessionStorage.getItem("store"))
        )
      );
    }

    //Save the status data in vuex to sessionStorage before page refresh
    window.addEventListener(
    	"beforeunload",()=>{
    	sessionStorage.setItem("store",JSON.stringify(this.$store.state));
    });
  }

This is to directly save an entire store locally, but most of the time we need to save only some key data locally. This is inflexible and extremely unfriendly to data that we don't want to put in vuex.

Improvement: datasessioncache js

Based on the above idea of caching data to local storage and then recovering when the page is loaded, I have made some improvements to the above method:

//dataSessionCache.js

let data = {};
let isFirst = false;

export default {
    register(id, obj, ...propertyKeys) {
        let hasId = Reflect.has(data, id);
        if (isFirst && hasId) {
            throw new Error('Duplicate id:\'' + id + '\'');
        } else if (hasId) {
            let obj_ = Reflect.get(data, id);

            let keys = propertyKeys == null ? Reflect.ownKeys(obj_) : propertyKeys;

            for (let key of keys) {
                obj[key] = obj_[key];
            }
        }
        Reflect.set(data, id, obj);
    },
    init(itemKey) {
        // Read the data in sessionStorage when the page is loaded
        let data_ = JSON.parse(sessionStorage.getItem(itemKey));
        if (data_) {
            data = data_;
        } else {
            isFirst = true;
        }

        // Save data to sessionStorage on page refresh
        window.addEventListener("beforeunload", () => {
            sessionStorage.setItem(itemKey, JSON.stringify(data));
        });
    }
}

usage

Step 1: initialization

Save the above code to a file named datasessioncache JS file,
Then in app The created hook in Vue initializes the init function. It needs to provide a itemName:

	//App.vue
    import dsc from "@/js/dataSessionCache.js";

    export default {
        created() {
        	/*The parameter itemKey will be used as sessionStorage
        	 getItem,setItem The uniqueness of the key during operation needs to be guaranteed*/
            dsc.init('data-local-caches');
        },
        //others
        ......
    };

Step 2: Register

For data in vue components

For data in vue components, such as data, write the data to be cached into an object, and then register in the created hook, for example:

 import dsc from "@/js/dataSessionCache.js";

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

	created(){
		//Note that the first parameter is ID. if the same ID is registered, an error will occur. Please ensure the uniqueness of the ID
		//The second parameter is the data object to be cached. It must be an object!
		sc.register('competent-cache-id', this.$data.cached);
	}
 };

For VueX store

A similar method can be used for the data in vuex store:

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

//App. In Vue
import dsc from "@/js/dataSessionCache.js";

export default {
	created() {
    	//Don't forget init
       dsc.init('data-local-caches');
       //register
       dsc.register('id-store',this.$store.state.cached);
    },
    //others
    ......
};

Not all attributes of the cache object

The prototype of register is register (ID, obj,... propertyKeys). The third parameter is used to specify the attributes to be cached. If propertyKeys is empty, all its attributes will be cached. For example, when we want to cache part of the data of a single text component without changing the original code, we can write as follows:

export default {
	data: () => ({
            a:1,
            b:'b'
        }),
        
	created() {
		//Cache only attribute a
    	dsc.register('cache-id',this.data,'a');
    },
    //others
    ......
}

benefit

  1. Save / restore data before and after page refresh, with less performance overhead
  2. Only a small amount of modification is required for the original code, or there is no need to modify the original code at all
  3. Easy to use, flexible and convenient, initialization and registration are OK, and the data to be cached can be flexibly specified

Topics: Javascript Front-end ECMAScript TypeScript Vue.js