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 tonewTodo
and executesaddTodo()
on enter.a list that loops over
todos
; displaying a checkbox bound totodo.completed
and a text node bound totodo.text
The Vue app is defined with two data objects:
newTodo
— which stores the value of the new “to do” text inputtodos
— which is an array of existing todo items (currently empty)
The app has a single method:
addTodo()
— pushes a new “todo” object to thetodos
array and then clears thenewTodo
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.
Problem
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.
Solution
The simple solution is to use LocalStorage to save data on the client. Caniuse.com 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 caniuse.com
The basic idea here is to listen for two events:
when the
todos
array changes, serialize it and save to LocalStoragewhen 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 Storage
If you close & reopen or refresh the page, your “to do” items persist!