This page looks best with JavaScript enabled

Working with Local Storage in Vue

 ·   ·  ☕ 7 min read

Here’s an high-level overview of local storage, popular options to get started on local storage in Vue, and how to choose an option that works for you.

Local Storage and Browsers

Browsers are windows to your web application. While it is easier to manage data access on your own servers, super secure and all, getting users to connect to the server for each and every task can be tiring and lead to a bad user experience. These are some use cases that highlight such problems -

  • Save data on a form that is not submitted yet
  • Save device-specific user preferences that are transient in nature (e.g. show image in portrait mode on mobile phones)
  • Provide limited browsing capabilities and user interaction even when user is offline (using PWA for example)

The obvious answers to such problems is to enable a “database” accessible by the web apps but present on the local device. But, this is made complicated by the nature of the web.

In the days of the old wild west, the only solution to storing local data was through “cookies”. Any and all local data including authentication, user preferences and what not were stored as key-value pairs in a file specific to the domain and managed by the browser. Cookies were good, but -

  1. Had limited storage
  2. Had to be included in every server request - irrelevant for non-auth data
  3. A few more problems of the old web that we are too afraid to get into

HTML5 upped the ante in the space by standardizing the way to store and manage data locally - affectionately called “local storage”. While local storage continues to store name-value pairs in some remote files, it has a few advantages over the older solution -

  1. No sending stuff to server. Local store is for local usage (unless you decide to do that for your own purposes)
  2. Higher storage limit - 5 MB for each domain + protocol
  3. Did I mention that the APIs for local store are standard across browsers?

All you need to do to access the store is write couple of lines of Javascript.

1
2
3
4
5
6
localStorage.message = "hello world";
localStorage.count = localStorage.count ? +localStorage.count + 1 : 1;

console.log(
  `Important message (displayed ${localStorage.count} times): ${localStorage.message}`
);

(see Codepen)

In the above example count would have reset every time the browser is refreshed - unless you stored it server-side or persisted it in cookies. With localStorage - count is stored in the local store, not sent to the server with each request, and fully accessible by the application. You can open the console to see count being incremented with each browser refresh.

Vue and Local Storage

Vue is just Javascript.

I know it is difficult to believe that since it seems so magical, but it is true. Vue brings reactivity, a great way to manage user experience, and easier way to manage states.

There are varying degrees of.. ahem, sophistication you can bring to work with local storage in Vue.

1. Directly Work with LocalStorage in Vue

Dealing with local storage is simple in Vue. But, before we get into that let’s see how “normal” code looks like.

Here’s a simple html template -

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<html>

<head>
  <link rel="stylesheet" href="https://unpkg.com/mvp.css">
</head>

<body style="text-align:center;">
  <h2>Simple Vue + Local Storage</h2>
  <br/>
  <div id="container">
    Hello, {{name}}!

    You have seen this {{count}} times.
    <br>
    If you remember across sessions, you would have seen this {{countstore}} times.
  </div>
</body>

</html>


And.. the Vue script..

1
2
3
4
5
6
7
8
new Vue({
  el: "#container",
  data: {
    name: "world",
    count: 0,
    countstore: 0,
  },
});

You will see this beautiful page.

vue-vanilla

You can see however, that the count is lost each time the browser is refreshed.

Let us improve it by introducing localStorage (with a slightly different syntax as compared to the previous example).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
new Vue({
  el: "#container",
  data: {
    name: "world",
    count: 0,
  },
  mounted() {
    if (!localStorage.getItem("countstore"))
      localStorage.setItem("countstore", 0);
    localStorage.setItem("countstore", +localStorage.getItem("countstore") + 1);
  },
  computed: {
    countstore() {
      return localStorage.getItem("countstore");
    },
  },
});

(See Codepen)

Now each time you refresh you continue seeing the same value in count but countstore is persistent and increments with each view.

vue-vanilla

2. Use a Package to Manage Variables in Components

While Vue works just fine with the above option, using variables within Vue components get mighty inconvenient. A cleaner approach may be to use one of the packages that abstract away the local storage.

This being Javascript we will ignore the fact that the “inconvenience” can be solved by just including a prototype. Instead we reward the work of others who have already solved the problem in the past.

Let us see an example by using Vue LS, a popular package that makes the local store available through a Vue prototype.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Vue.use(VueStorage);

new Vue({
  el: "#container",
  data: {
    name: "world",
    count: 0,
  },
  mounted() {
    if (!this.$ls.get("countstore")) this.$ls.set("countstore", 0);
    this.$ls.set("countstore", +this.$ls.get("countstore") + 1);
  },
  computed: {
    countstore() {
      return this.$ls.get("countstore");
    },
  },
});

(See Codepen).

The results are same as earlier. You can use Vue-LS (or a comparable alternative) in components, mixins, or any other part of Vue.

3. Use Vuex + Local Store

Vuex is the state management library for Vue. It vastly simplifies a central storage location that is accessible from any Vue component.

Rewriting our script using Vuex..

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var store = new Vuex.Store({
  state: {
    name: "world",
    count: 0,
    countstore: 0,
  },
  mutations: {
    incrCountStore(state) {
      state.countstore++;
    },
  },
});

new Vue({
  el: "#container",
  store,
  mounted() {
    this.$store.commit("incrCountStore");
  },
  computed: {
    countstore() {
      return this.$store.state.countstore;
    },
    count() {
      return this.$store.state.count;
    },
    name() {
      return this.$store.state.name;
    },
  },
});

It is very much possible to use vue-ls (or comparable solutions) with Vuex. All you need to do is to keep getting and setting variables every time a state is changed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// ...

// get state
export const state = () => ({
  count: ()=>this.$ls.get("count"),
  // well, typically you set `count` in Vuex at app startup
  // by retrieving value from localstore
});

// ...

// set state - typically done with each mutation
export const mutations = {
  setCount(state, count) {
    state.count = count;
    this.$ls.set("count", count);
  },

As you can imagine, setting tens (or hundreds?) of variables is not quite a fun thing to do.

Again, this is Javascript and someone have already solved this problem for us. Enter solutions like vuex-persistedstate and vuex-persist that automatically synchronize vuex states with local storage.

We will look at an example of using vuex-persistedstate. Just add a single line to include the createPersistedState plugin while defining the store. Rest of the code in the Vuex example will remain as-is.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var store = new Vuex.Store({
  // ...
  plugins: [createPersistedState()],
});

new Vue({
  el: "#container",
  store,
  //   ...
});

Refresh the browser and you see countstore being persisted across sessions.

Which option is better?

We saw three ways of working with local store in Vue. You may start from the simplest option or choose one that fits your project.

  • If I am working with simple Vue frontend and don’t quite have anything to do with managing state, I would use a solution like vue-ls. It makes things easier and everyone loves tidy code.
  • If I am working with Vuex, I invariably gravitate towards vuex-persist. I tend to work with states that need to persist across sessions - storing state in local store gives me a “clean” way to get stuff done quickly

While I am not saying everyone should choose Vuex, I encourage everyone to carefully evaluate their situation and always choose the hammer that is Vuex (/s). Pair it with one of the ‘store persistence’ solutions and you will never regret getting into web development :).

Stay in touch!
Share on

Prashanth Krishnamurthy
WRITTEN BY
Prashanth Krishnamurthy
Technologist | Creator of Things


What's on this Page