Add LocalStorage to your Vue app in 2 lines of code

Add LocalStorage to your Vue app in 2 lines of code

Say you already have your Vue app up and running, but you want your users to be able to save their state between usage sessions. How can you achieve this? If using LocalStorage is an option, it is very easy!

A non-LocalStorage app

Say we have a simple “to do” app. Here’s what it might look like:

The app template is made out of two basic components:

  • an <input> that’s bound to newTodo and executes addTodo() on enter.

  • a list that loops over todos; displaying a checkbox bound to todo.completed and a text node bound to todo.text

The Vue app is defined with two data objects:

  • newTodo — which stores the value of the new “to do” text input

  • todos — which is an array of existing todo items (currently empty)

The app has a single method:

  • addTodo() — pushes a new “todo” object to the todos array and then clears the newTodo text input

Near the bottom of the app, I’ve placed some code to be executed when the app is mounted(). For now, it just logs the event to the console.

Finally, I’ve added a watcher on the todos array:

watch: {
  todos: {
    handler() { console.log('Todos changed!'); },
    deep: true,

For now, the handler just logs the event to the console. Note the deep property is set to true. This is important, as it directs Vue to look at all nested properties inside the array.


As simple as it is, the app works just fine; You can add new “to do” items, and then toggle them completed or not.

But what happens when the user closes or refreshes the page? Everything is lost.


The simple solution is to use LocalStorage to save data on the client. describes LocalStorage as…

[A] method of storing data locally like cookies, but for larger amounts of data.

The browser support is very nice.

[LocalStorage support table]( from []( support table from

The basic idea here is to listen for two events:

  • when the todos array changes, serialize it and save to LocalStorage

  • when the app mounts, get the data from from LocalStorage, deserialize it, and update the todos array.

The first event will be handled with the watcher we already have in place. Just add one line:

watch: {
  todos: {
    handler() {
      console.log('Todos changed!');
      localStorage.setItem('todos', JSON.stringify(this.todos));
    deep: true,

With that line in place, when the app’stodos array is changed, LocalStorage’stodos key is set to a stringified version of the array.

The second event will be handled with the mounted() lifecycle hook:

mounted() {
  console.log('App mounted!');
  if (localStorage.getItem('todos')) this.todos = JSON.parse(localStorage.getItem('todos'));

The line above first checks to see if there is a todos key in LocalStorage. If so, it parses it and sets the app’s todos array.

That’s it! With those two lines, our app works as expected.

If you open up DevTools (F12) and go to the Application tab, you can see our key/value pair set in the Local Storage section.

See the `todos` key in Local StorageSee the todos key in Local Storage

If you close & reopen or refresh the page, your “to do” items persist!