Movatterモバイル変換


[0]ホーム

URL:


Mike Street

Vue: Using localStorage with Vuex store

ByMike Street

Posted on13th October 2017.7 mins reading time
I wrote a book about Vue.js!Vue.js 2.x by Example is available as from Packt and covers Vue, Vuex and VueRouter.

This tutorial uses Vue v2.4.4 and Vuex v2.5.0 - although I'm sure it will work with previous versions

localStorage basics

localStorage is a cache in the browser which persists even after the browser is closed. It allows you to store data on a page and later access it - it's especially easy to do using JavaScript. More information aboutlocalStorage can be found on theMDN Website, but the basics are as follows. Thekey is an identifiable string for you to access the saved data later.

// Store the "value" under the ID of "key"localStorage.setItem('key','value');// Load the data back and store as a variablelet val= localStorage.getItem('key');// val will equal "value"

Note:

localStorage canonly contain strings. This means that any objects or arrays you wish to store inlocalStorage must be converted to a JSON string, and then re-formatted when you retrieve them.

For example:

// Convert the object into a JSON string and storelocalStorage.setItem('key',JSON.stringify(object));// Retrieve the data and convert from JSOn string to object/arraylet obj=JSON.parse(localStorage.getItem('key'));

Vuex

Vuex is a centralised state management tool for Vue. It gives you a central store that all of your components can access, update and react to changes. Unless you are doing a very simple (in functionality) Vue app, it is highly recommended you use Vuex for all of the management of your data and states.

Using localStorage with Vuex

On the latest Vue app I'm developing, I wanted the Vuex contents (orstate) to be stored inlocalStorage whenever it was updated. This meant that at any time the user could close their browser and, when they return, have the app in the same state as when they left it. Be it products in the basket or user preferences, I wanted the app to remember what they had chosen.

Initialise the store

If you're reading this I would assume you've got your store already initialised. However you've built your app, thestore should have a variable assigned to it.

// Initialise your storeconst storenewVuex.Store({// You state might be more complex than thisstate:{count:1},mutations:{},getters:{}});

Storing data

We now wish to cache the data whenever the store updated. Fortunately, Vuex offers asubscribe function which triggers whenever the store updates.

After your store has been initialised, register the subscribe method on yourstore variable. This function accepts two parameters - the mutation which was fired and the stateafter the mutation. We wish to store this state in ourlocalStorage. AslocalStorage is specific to each domain name, we can use a variable name to reference the contents - such asstore. Don't forget to convert your object to a string.

// Subscribe to store updatesstore.subscribe((mutation, state)=>{// Store the state object as a JSON stringlocalStorage.setItem('store',JSON.stringify(state));});

Retrieving data

With our data now stored with every update, we need to retrieve the data on page load. When the user re-accesses the app, we need to replace the existing, empty store with the contents of our storage.

To do this, we are going to create a mutation within the store, which updates the state, and trigger this when the app is created.

Create a new mutation calledinitialiseStore. Inside this mutation, check if thelocalStorage item exists

const storenewVuex.Store({state:{count:1},mutations:{initialiseStore(state){// Check if the ID existsif(localStorage.getItem('store')){}}},getters:{}});

We now need to replace the current state if it does exist. To do this, we are going to use thereplaceState Vuex method. Within here, we are going to merge both the current, blank, state and the stored data. The reason for this is so that if there are any new properties which were added since the last time the user visited, they don't get any dreadedundefined errors.

const storenewVuex.Store({state:{count:1},mutations:{initialiseStore(state){// Check if the ID existsif(localStorage.getItem('store')){// Replace the state object with the stored itemthis.replaceState(Object.assign(state,JSON.parse(localStorage.getItem('store'))));}}},getters:{}});

The last stage is to call this mutation when the Vue app is created. We want this to happen at theearliest point which, based on theVue lifecycle hooks is during thebeforeCreate() method.

Add this method to your Vue instance and trigger the mutation:

newVue({el:'#app',store,beforeCreate(){this.$store.commit('initialiseStore');}});

Huzzah! You now have an app with a Vuex store cached inlocalStorage.

If you found this post useful I would appreciate if you consideredchucking a couple of quid my way. Thanks!


Update 20/10/17

Cache Validity

While using this in a project recently, I experienced an odd sensation where changes I made were not being reflected. This is because I had altered thestore structure without clearing mylocalStorage. Adding values was fine, but renaming, editing or altering a value's type did not change.

Although not an issue for me, as I can clear the cache, if some code were to be pushed live, this could affect users who had visited the site before.

Fortunately, I was usingsemver for my versioning (and even if you're not - this will work as long as you version each release somehow) and so I could call upon ver version number to check if the store was up to date.

If on load, the user had the same version number as that of my app, then the cache was fine. If it's different, clear the cache and load a new version.

Be warned This will clear thewhole cache, so if you are relying on it for user preferences or similar, you may wish to do the selective deletion.

The first step is to load our version number. Ours is stored in thepackage.json so, using ES6, this is as simple as:

import{version}from'./package.json';

However, you may wish to cache yours from a git tag or have it somewhere as a variable. Ideally, it needs to be accessed separately from the store so that the cache doesn't end up overwriting it.

Next, create an empty string in your store - for the version to be saved once verified.

state:{// Cache versionversion:'',count:1},

We can now update ourinitialiseStore mutation to check the version with that of the one in the cache and take appropriate action based on the result

initialiseStore(state){// Check if the store existsif(localStorage.getItem('store')){let store=JSON.parse(localStorage.getItem('store'));// Check the version stored against current. If different, don't// load the cached versionif(store.version== version){this.replaceState(Object.assign(state, store));}else{state.version= version;}}}

Update 25/10/17

Selective Caching

You may only wish to cache a few elements from your store, this can be achieved by creating a new object in yoursubscribe function and storing that. We are already merging the cache with the current store state on load, so that doesn't need to change.

store.subscribe((mutation, state)=>{let store={version: state.version,count:1};localStorage.setItem('store',JSON.stringify(store));});
WebJavascriptFront-end DevelopmentVueJS

View this post on Github

Powered bywebmentions

Links

🔗

You might also enjoy…

Mike Street

Written byMike Street

Mike is a CTO and Lead Developer from Brighton, UK. He spends his time writing, cycling and coding. You can find Mike onMastodon.


[8]ページ先頭

©2009-2025 Movatter.jp