Within your Vue application, you may wish to calculate or manipulate data in a consistent or repetitive way or run tasks that require no output to your view.For example, if you wanted to calculate the sales tax on every price or retrieve some data from an API before assigning it to some variables.
Rather than creating computed functions for each time, we need to do this, Vue allows you to create functions or methods. These get declared in your application and can be accessed from anywhere - similar to the data or computed functions.
Add a method object to your Vue application and note the updates to the data object:
const app = new Vue({
el: '#app',
data: {
shirtPrice: 25,
hatPrice: 10,
currency: '$',
salesTax: 16
},
methods: {
}
});
Within the data object, the price key has been replaced with two prices - shirtPrice and hatPrice. We'll create a method to calculate the sales tax for each of these prices.
Similar to creating a function for the computed object, create a method function title called calculateSalesTax. This function needs to accept a single parameter, which will be the price. Inside, we will use the code from the previous example to calculate the sales tax. Remember to replace this.price with just the parameter name: price, as shown here:
methods: { calculateSalesTax(price) { // Work out the price of the item including
sales tax return parseFloat( Math.round((this.salesTax / 100) * price)
+ price).toFixed(2); } }
Pressing save will not do anything to our application - we need to call the function. In your view, update the output to use the function and pass in the shirtPrice variable:
<div id="app">
{{ calculateSalesTax(shirtPrice) }}
</div>
Save your documents and check the result in the browser - is it what you expected? The next task is to prepend the currency. We can do that by adding a second method that returns the parameter passed into the function with the currency at the beginning of the number:
methods: {
calculateSalesTax(price) {
// Work out the price of the item including
sales tax
return parseFloat(
Math.round((this.salesTax / 100) * price) +
price).toFixed(2);
},
addCurrency(price) {
return this.currency + price;
}
}
In our view, we then update our output to utilize both methods. Rather than assigning to a variable, we can pass the first function, calculateSalesTax, as the parameter for the second addCurrency function. This works because of the first method, calculateSalesTax, accepts the shirtPrice parameter and returns the new amount. Instead of saving this as a variable and passing the variable into the addCurrency method, we pass the result directly into this function, which is the calculated amount:
{{ addCurrency(calculateSalesTax(shirtPrice)) }}
However, it would start to get tiresome having to write these two functions every time we needed to output the price. From here, we have two options:
- We can create a third method, titled cost() - which accepts the price parameter and passes the input through the two functions
- Create a computed function, such as shirtCost, which uses this.shirtPrice instead of having a parameter passed in
We could, alternatively, create a method titled shirtCost that does the same as our computed function; however, it's better to practice to use computed in this case.
This is because computed functions are cached, whereas method functions are not. If you imagine our methods being a lot more complicated than they currently are, calling function after function repeatedly (for example, if we wanted to display the price in several locations) could have a performance impact. With computed functions, as long as the data does not change, you can call it as many times as you want, with the result being cached by the application. If the data does change, it only needs to recalculate once, and re-cache that result.
Make a computed function for both the shirtPrice and hatPrice, so that both variables can be used in the view. Don't forget that to call the functions internally you must use the this variable - for example, this.addCurrency(). Use the following HTML code as the template for your view:
<div id="app">
<p>The shirt costs {{ shirtCost }}</p>
<p>The hat costs {{ hatCost }}</p>
</div>
Have a go at creating the computed functions yourself before comparing against the following code. Don't forget that there are many ways to do things in development, so don't worry if your code works but doesn't match the following example:
const app = new Vue({
el: '#app',
data: { shirtPrice: 25, hatPrice: 10, currency: '$', salesTax: 16 }, computed: { shirtCost() { returnthis.addCurrency(this.calculateSalesTax(
this.shirtPrice)) }, hatCost() { return this.addCurrency(this.calculateSalesTax(
this.hatPrice)) }, }, methods: { calculateSalesTax(price) { // Work out the price of the item including
sales tax return parseFloat( Math.round((this.salesTax / 100) * price) +
price).toFixed(2); }, addCurrency(price) { return this.currency + price; } } });
The result, although basic, should look like the following: