Persisting Vue State with localStorage
localStorage is a straightforward way to keep small amounts of user data between sessions without standing up a backend. It works well for preferences, progress markers, and similar lightweight state. Combined with Vue's reactivity system, persisting data is only a few lines of work.
A Practical Checklist
Consider a simple todo-style checklist. Each item in the list can be marked as completed, and that state should survive a page refresh. The component holds the list of available items plus an array tracking which ones the user has checked.
export default {
data() {
return {
checked: [],
todos: [
"Set up nuxt.config.js",
"Create Pages",
// ...
]
}
}
}
The template renders each item with a checkbox bound to the checked array:
<div id="app">
<fieldset>
<legend>
What we're building
</legend>
<div v-for="todo in todos" :key="todo">
<input
type="checkbox"
name="todo"
:id="todo"
:value="todo"
v-model="checked"
/>
<label :for="todo">{{ todo }}</label>
</div>
</fieldset>
</div>
Persisting on Mount and Watch
At this point, the UI responds to clicks but nothing is saved. Two things need to happen: read any existing data from localStorage when the component loads, and write back whenever the checked state changes.
In the mounted hook, the stored JSON string is parsed back into an array so the UI reflects what was previously saved:
mounted() {
this.checked = JSON.parse(localStorage.getItem("checked")) || []
}
To keep the stored data in sync, a watcher on the checked property serializes the array back to JSON and writes it to localStorage on every change:
watch: {
checked(newValue, oldValue) {
localStorage.setItem("checked", JSON.stringify(newValue));
}
}
Scope of the Pattern
That is the entire implementation for this use case. The same idea extends naturally to other personal, low-volume data a user might want to keep locally—no server, no database, no configuration required.



