Calculate properties and listener details
- 2021-12-04 18:03:53
- OfStack
1. Calculate attributes
Expressions in templates are very convenient, but they were originally designed for simple operations. Putting too much logic into a template makes it overweight and difficult to maintain.
For example:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
In this place, templates are no longer simple declarative logic. You have to look at it for a while to realize that this is the variable you want to display
message
Gets or sets the flipped string of the. When you want to include this flip string in multiple places in the template, it will be more difficult to handle.
Therefore, for any complex logic, you should use computed attributes.
1.1 Basic Examples
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// Object of the computed property getter
reversedMessage: function () {
// `this` Point vm Instances
return this.message.split('').reverse().join('')
}
}
})
Results:
Original message: "Hello"
Computed reversed message: "olleH"
Here we declare a computed attribute
reversedMessage
. The function we provide will be used as
property vm.reversedMessage
Adj.
getter
Function:
console.log(vm.reversedMessage) // => 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // => 'eybdooG'
You can open the browser console and modify the
vm
.
vm.reversedMessage
The value of always depends on the value of
vm.message
The value of.
You can bind like ordinary
property
1. Bind the calculation attribute in the template. Vue knows
vm.reversedMessage
Depend on
vm.message
, so when
vm.message
When a change occurs, all dependencies
vm.reversedMessage
The binding of is also updated. And best of all, we have created this dependency declaratively: the
getter
The function is free of side effects (side effect), which makes it easier to test and understand.
1.2 vs Method for Computing Attribute Cache
You may have noticed that we can achieve the same effect by calling methods in expressions:
<p>Reversed message: "{{ reversedMessage() }}"</p>
// In a component
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
We can define the same 1 function as a method instead of a calculated property. The final result of the two methods is exactly the same. However, the difference is that computed attributes are cached based on their responsive dependencies. They are re-evaluated only when the related responsive dependencies change. This means that as long as
message
Haven't changed yet, multiple visits
reversedMessage
The evaluated property immediately returns the previous evaluation results without having to execute the function again.
This also means that the following computed properties will not be updated because Date. now () is not a responsive dependency:
computed: {
now: function () {
return Date.now()
}
}
In contrast, whenever a re-rendering is triggered, the calling method will always execute the function again.
Why do we need caching? Suppose we have a computational attribute with high performance overhead
A
It needs to traverse a huge array and do a lot of calculations. Then we may have other computed attributes that depend on
A
. Without caching, we will inevitably execute many times
A
Adj.
getter
! If you don't want to have cache, please use method instead.
1.3 Computed Attributes vs Listening Attributes
Vue
Provides a more general way to observe and respond
Vue
Data changes on the instance: listen for attributes. When you have one data that needs to change with other data, you are easy to abuse it
watch
--especially if you've used it before
AngularJS
. However, it is generally better to use computed attributes instead of imperative
watch
Callback.
Consider this example:
<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 above code is imperative and repetitive. Compare it to the version of the calculated property:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
Much better, isn't it?
1.4 setter for Calculated Attributes
getter is the default calculation attribute, but you can also provide 1 setter when necessary:
// ...
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
// ...
Run again now
vm.fullName = 'John Doe'
When,
setter
Will be called,
vm.firstName
And
vm.lastName
Will be updated accordingly.
2. Listeners
Although computed properties are more appropriate in most cases, a custom listener is sometimes required. That's why
Vue
Pass
watch
Option provides a more general way to respond to changes in data. This is most useful when you need to perform asynchronous or costly operations as the data changes.
For example:
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<!-- Because AJAX The ecology of libraries and general tools is quite rich, Vue There is no duplication of core code -->
<!-- Provide these functions to keep them lean. It also gives you the freedom to choose tools that you are more familiar with. -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/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 `question` Change, this function will run
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
created: function () {
// `_.debounce` Yes 1 A pass Lodash A function that limits the frequency of operation.
// In this example, we want to restrict access yesno.wtf/api Frequency of
// AJAX The request will not be issued until the user has entered it. Want to know more about
// `_.debounce` Function ( And their close relatives `_.throttle`) Knowledge,
// Please refer to: https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
getAnswer: 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
})
}
}
})
</script>
Results:
Ask a yes/no question:
I cannot give you an answer until you ask a question!
In this example, use the
watch
Option allows us to perform an asynchronous operation (access 1 API), limits how often we perform this operation, and sets an intermediate state until we get the final result. These are all things that computed attributes can't do.