1: computed attribute VS methods attribute
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
<p>Computed reversed message: "{{ reversedMessage1() }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
methods: {
reversedMessage1: function () {
return this.message.split('').reverse().join('')
}
},
computed: {
// a computed getter
reversedMessage: function () {
// `this` points to the vm instance
return this.message.split('').reverse().join('')
}
}
})
We found that defining the same function as a method, or computed for the final result is exactly the same, will change as the dependency value changes. However, the difference is that computational attributes are cached based on their dependencies.
Why do we need caching? Suppose we have a computational attribute A with high performance overhead, which requires traversing a large array and doing a lot of computations. Then we may have other computational properties that depend on A. If there is no cache, we will inevitably execute A getter many times! If you don't want a cache, use method instead.
2: computed attribute VS watch attribute
1: Usually a better idea is to use the computed attribute rather than the imperative watch callback.
<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
The code in the watch attribute above is imperative and repetitive. The following method is relatively simple
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
2: getter,setter for calculating attributes
computed:{
fullName:{
//get reacts to dependency changes to computational attributes
get:function(){
return this.first.name+' '+this.lastname
},
//set reacts to dependency values in order to change computational attributes
set:function(newValue){
var names=newValue.split(' ')
this.fistname=names[0]
this.lastname=names[names.length-1]
}
}
}
Now when vm.fullName = John Doe is run again, setter is called, and vm.firstName and vm.lastName are updated accordingly.
3: The watch function must be used
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<script src="https://unpkg.com/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// If the question changes, the function runs
question: function (newQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.getAnswer()
}
},
methods: {
// _ debounce is a function that restricts the operating frequency through lodash.
// In this example, we want to limit the frequency of access to yesno.wtf/api
// ajax requests are not sent until the user has finished typing
// Learn more about. debounce function (and its cousin)
// _ throttle), refer to: https://lodash.com/docs#debounce
getAnswer: _.debounce(
function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
var vm = this
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
},
// This is the number of milliseconds we stopped waiting for the user to enter
500
)
}
})
</script>
In this example, using the watch option allows us to perform an asynchronous operation (accessing an API), limits the frequency at which we perform the operation, and sets the intermediate state before we get the final result. This is not possible with computational attributes.