Writing a Pomodoro Timer with Vue.js - Part 2
This second part allows all of the task records to be saved and across browser sessions with Local Storage. Check out part 1 if you haven't already.
The source on GitHub and the app itself is hosted here on GitHub pages.
Adding Local Storage functionality
Writing data to Local Storage
Local Storage is a key-value system store in the browser where both the key and value are strings. When you try to write an object instance into the value, this happens.
So how do we fix this? As mentioned earlier, Local Storage accepts both inputs as strings. That means, we have to stringify our data before we write it to the Local Storage. With an implementation like this, there are trade-offs.
Stringify = cast the JSON object into a string
- We cannot set an automatic expiry date for data in Local Storage
- Anyone with our domain can access the data
- Stringifying/Parsing a large JSON object could potentially have an impact on performance
But, since our JSON is pretty small and this is a side project, we will just use Local Storage for convenience.
Reading from Local Storage
Since Local Storage stores both values as strings, we have to parse our data into an object before we can do anything meaningful to it.
Reading the string value from Local Storage and Parsing it to an object.
Note: In our implementation, we are storing JSON objects into the Local Storage, that is why we have to parse. If you are writing strings directly into Local/Session Storage (like assigning an access token), you do not have to parse/stringify the value.
Implementing Local Storage
Now that we know how to read and write JSON data from Local Storage, let's implement that into our timer.
In this example, we only want to bind our taskDone
array to the Local Storage of tasks
.
The mounted API
Looking at the life cycle of VueJS, we will want our Local Storage to be read and copied to our data as soon as we can. Using the mounted API, we can read as soon as our Vue app is mounted to the page. Since our Local Storage feature do not depend on any child elements, we can safely carry out the read operation right after the element is mounted.
The watch method
The watch method in VueJS allows us to run a handler (a function that handles event changes) whenever a data is changed.
By attaching a handler to the taskDone
array, we can set the taskDone
array to Local Storage every time it is changed by overwriting the tasks
key-value in Local Storage. We need to handle visibility of the Clear History button appropriately too.
What can be done better?
Writing the Local Storage functionality twice can be very verbose. If we are using the Local Storage functionality multiple times, it can unnecessarily increase the length of our source. To tackle that, I abstracted the read and write logic into the utils.js script (where I store most of the non-application specific code).
When accessing data from the Local Storage, we went from this
// writing to Local Storage
window.localStorage.setItem('tasks', JSON.stringify(this.taskDone));
// reading from Local Storage
this.taskDone = JSON.parse(window.localStorage.getItem('tasks'));
To this
// writing to Local Storage
writeLS('tasks', this.taskDone);
// reading from local storage
this.taskDone = readLS('tasks');
To summarise
In this update:
- Added read and write to Local Storage functionality
- Implemented read and write to Local Storage via Utils.js
- Added JSDocs for all Utils.js functions
Additional Reading materials
Documentation for LocalStorage from Mozilla
https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
JSON Stringify
https://www.w3schools.com/js/js_json_stringify.asp
Life Cycle of VueJS
https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram
Photo by Julien Bachelet from Pexels