⏰ 4: Create a Computed Property to Display A Date (intermediate)
Project Goal | Learn about computed properties by building a simple app that calculates the days since your birthday |
---|---|
What you’ll learn | You will learn how computed properties work and how to use them. |
Tools you’ll need | A modern browser like Chrome/Firefox. Access to CodeSandbox. |
Time needed to complete | 10 minutes |
Create a Simple Computed Property
Today you will create a very simple application that calculates the number of days since your birthday. You'll also learn about how computed properties work and how you can use them in your own projects.
Get Started
Head over to CodeSandbox and create a new Vue template.
The sandbox will set up a new Vue application where you can write your code, and it will be automatically compiled and rendered in the window on the right.
Preliminary Code Clean Up
Go to App.vue
and remove everything from inside the div
with the id #app
. Also clear the <script>
tag, but leave the export
statement, as you'll need it soon. You can keep the code inside the <style>
blocks as it won't get in your way. In the end, your file should look like this:
<template>
<div id="app">
</div>
</template>
<script>
export default {
};
</script>
2
3
4
5
6
7
8
9
10
11
The reason you're doing this is so that you have a clean slate without all the boilerplate code Codesandbox adds.
Setting up a label and form input
Now set up a <p>
tag to display our result, and an <input>
element so you can tell the app when your birthday is. Go inside the <div id="app">
block and add:
<div id="app">
<input v-model="birthdate" type="text" placeholder="Enter your birthday here" />
<p>
Days since my birthday: <strong>{{ daysSinceBirth }}</strong>
</p>
</div>
2
3
4
5
6
Right now it won't work and you will probably get some errors since you are missing some properties. Start with the v-model="birthday"
prop, in which you will store your input.
Head over to the export
block, and add a new local data store.
data() {
return {
birthdate: null
};
}
2
3
4
5
Next, you will need a function that calculates the times between two given dates. Add a new method
.
methods: {
daysBetween(date1, date2) {
//Get 1 day in milliseconds
const dayInMs = 1000 * 60 * 60 * 24;
// Convert both dates to milliseconds
const dayOneInMs = date1.getTime();
const dayTwoInMs = date2.getTime();
// Calculate the difference in milliseconds
const differenceInMs = dayTwoInMs - dayOneInMs;
// Convert back to days and return
return Math.round(differenceInMs / dayInMs);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Creating a computed property
Computed properties are functions
that can calculate a value and return data that will be used in your template. In your case, you will use them to calculate the number of days between a user's birthday and today's date. Then you will return it as a number that can be displayed inside your <p>
tag.
This type of logic would be cumbersome to maintain if placed inside line blocks on a template, and may even be impossible if the logic is too complex due to the templating engine limitations.
The rule of thumb is, whenever you need to calculate
a value reactively when another property changes - use computed properties. In this case, you want to calculate the number of days every time a user changes the date inside the <input>
. This input is attached to the data
storage with the birthday
property. You will use this property inside a computed
property and it will become its dependency. (Don't worry, Vue will do this behind the scenes and automatically figure out that your computed property depends on birthday
to be calculated).
Go ahead and create a computed property block inside the export default
block to calculate the daysSinceBirth
that you defined in your template:
computed: {
daysSinceBirth() {
if (!this.birthdate) return 0;
return this.daysBetween(new Date(this.birthdate), new Date());
}
}
2
3
4
5
6
7
Computed properties are always defined as functions inside the computed
property of an export object.
First, you are checking that the birthday
property has already been defined inside an if
statement. If it's still null you will simply return 0.
After, you calculate the number of days between the first date, the date the user inputs
, and the second date today
.
💡
Javascript's Date
will return today's date when it recieves no arguments.
Reload your app and type up your birth date on the input field. You will see as you type that the app is actually recalculating the value of daysSinceBirth
with each keystroke. This happens because its dependencies
are changing, in this case - our data property birthdate
!
💡
Computed properties behave the same way as functions? If you're asking yourself this question you're on the right track. The short answer is yes, they both execute a function and return a result that is then used on your template to change some behavior. The long and correct answer is, no.
Methods are executed EVERY TIME the app needs to get a value. So every time a component is rendered, for example, the whole function needs to be re-executed to return the value. This can be OK for simple methods, but if you are v-for
looping through a hundred items, the performance can start to take a hit.
Computed properties on the other hand can cache their result based on the dependencies of the function. In very simple terms, if your computed property is calculating something based on one of your static properties for example, it won't be re-executed until this second property changes!
The entire code of your App.vue
file should look like this:
<template>
<div id="app">
<input
v-model="birthdate"
type="text"
placeholder="Enter your birthday here"
/>
<p>
Days since my birthday: <strong>{{ daysSinceBirth }}</strong>
</p>
</div>
</template>
<script>
export default {
data() {
return {
birthdate: null
};
},
computed: {
daysSinceBirth() {
if (!this.birthdate) return 0;
return this.daysBetween(new Date(this.birthdate), new Date());
}
},
methods: {
daysBetween(date1, date2) {
//Get 1 day in milliseconds
var one_day = 1000 * 60 * 60 * 24;
// Convert both dates to milliseconds
var date1_ms = date1.getTime();
var date2_ms = date2.getTime();
// Calculate the difference in milliseconds
var difference_ms = date2_ms - date1_ms;
// Convert back to days and return
return Math.round(difference_ms / one_day);
}
}
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Conclusion and Challenge
Understanding the importance and use of computed properties is key to developing more powerful and complex Vue applications.
Your challenge today, is to create a computed property that will display your name in reverse! Hint You will need to split
your name string into an array, and reverse
it.
Good luck!
Badge
Congratulations! You have earned a badge!
Author
Made with ❤️ by Marina Mosti