On Vue.js documentation there is an example like below:
var vm = new Vue({
el: \'#demo\',
data: {
firstName: \'Foo\',
lastName: \'Bar\',
full
Vue.js is reactive
That means it is able to react to things like user input and data changes. I recommend reading up on the reactivity system to have a better understanding of the mechanics Vue is using under the hood when a data change is observed. There are three main ways to have your components make use of Vue’s reactive nature. These are Methods, Computed Properties and Watchers. Without some scrutiny, these options may seem interchangeable (and in some ways they are) but each of them has their best use case scenario. To help illustrate the examples, I will make a small grading app that allows a teacher to input test scores for students in their class, view the average grade and set up the scaffolding for an auto-save feature.
METHODS
TL;DR – Use methods when you want to alter a component’s state or when an event has occurred that isn’t necessarily related to the instance data being mutated. Methods can take arguments but do not keep track of any dependencies. When you use a method, it usually creates some side effect within the component and methods are run each time the component is reloaded. This means if the UI is updated very frequently, this method (and any other methods on the component) will run as well. This could cause performance issues or lag in the UI.
Below is the beginning of our grading app. There is no validation or anything and its not pretty, I know. We have a small set of tests in our data object (student name and score). And a method we can use to add another test object to our data property ‘tests’.
new Vue({
el: "#app",
data: {
newTest: {
studentName: '',
score: 0
},
tests: [{
studentName: "Billy",
score: 76
}, {
studentName: "Suzy",
score: 85
}, {
studentName: "Johnny",
score: 89
}, {
studentName: "Emma",
score: 93
}]
},
methods: {
addTestScore: function() {
this.tests.push({
studentName: this.newTest.studentName,
score: this.newTest.score
});
this.newTest.studentName = '';
this.newTest.score = 0;
}
}
});
-
{{test.studentName}} - {{test.score}}
Student
Score
COMPUTED PROPERTIES
TL;DR – Use a computed property when you want to mutate a property that is dependent upon another property being changed. Computed properties are typically dependent on other data properties. Any change to the dependent properties will trigger the logic for the computed property. Computed properties are cached based on their dependencies so they will only rerun if a dependency changes. (For example, a computed property that returns a new Date() will never rerun because the logic will never run more than 1 time) Computed properties are getters by default but a setter function can be set if needed to achieve similar functionality.
In our grading app, we want to keep track of the average test score as we enter more data. Let's add a computed property called ‘average’ that will return the average score of the tests in our dataset. The ‘average’ computed property will be updated any time we add another test score.
new Vue({
el: "#app",
data: {
newTest: {
studentName: '',
score: 0
},
tests: [{
studentName: "Billy",
score: 76
}, {
studentName: "Suzy",
score: 85
}, {
studentName: "Johnny",
score: 89
}, {
studentName: "Emma",
score: 93
}]
},
computed: {
average: function() {
var sum = this.tests.reduce(function(acc, test) {
return acc + Number(test.score);
}, 0);
return (sum / this.tests.length).toFixed(2);
}
},
methods: {
addTestScore: function() {
this.tests.push({
studentName: this.newTest.studentName,
score: this.newTest.score
});
this.newTest.studentName = '';
this.newTest.score = 0;
}
}
});
Average Score: {{average}}
-
{{test.studentName}} - {{test.score}}
Student
Score
WATCHERS
TL;DR – Use watchers when you need to perform some logic as a result of a change that took place on a specific data property. Watched properties only act on one property. This is most useful when you want to perform asynchronous or expensive operations in response to changing data. Keep in mind watchers only change when that specific data property changes.
Let us pretend the end user of our little grading app is a professor with 300 tests to grade. That can take a long time. An auto-save feature would be nice to have in case our end user gets to the end of the pile of tests and forgets to manually hit save. In our code lets add a watcher to our previously created computed property ‘average’. Whenever it is changed (as a result of a new test score being added and the average being updated) let's call a new ‘autosave’ method that could be used to call an API and save our test scores.
new Vue({
el: "#app",
data: {
newTest: {
studentName: '',
score: 0
},
tests: [{
studentName: "Billy",
score: 76
}, {
studentName: "Suzy",
score: 85
}, {
studentName: "Johnny",
score: 89
}, {
studentName: "Emma",
score: 93
}]
},
watch: {
average: function() {
this.autosave();
}
},
computed: {
average: function() {
var sum = this.tests.reduce(function(acc, test) {
return acc + Number(test.score);
}, 0);
return (sum / this.tests.length).toFixed(2);
}
},
methods: {
addTestScore: function() {
this.tests.push({
studentName: this.newTest.studentName,
score: this.newTest.score
});
this.newTest.studentName = '';
this.newTest.score = 0;
},
autosave: function() {
//pretend we are calling our backend to save the data
console.log('calling api, saving data');
}
}
});
Average Score: {{average}}
-
{{test.studentName}} - {{test.score}}
Student
Score