This is the seventh day of my participation in the August More text Challenge. For details, see:August is more challenging
Both computed and Watch observe the data changes on the page, but there are certain differences.
1.computer: calculates attributes
1.1 What are computed Attributes
The key to calculating a property is the word attribute (attribute is a noun), first of all it is a property and second of all it has the ability to calculate (calculate is a verb), the calculation is a function;
Simply put, it’s a property that caches the results of a computation (turning the behavior into a static property), and that’s it!
- Monitor custom variables. This variable must not be the same as the variables in data and props.
- For a computed property, the default get method (which must have a return value) is used.
- Support caching, only the dependent data changes will be recalculated, otherwise the data will be taken from the cache;
- Async is not supported, and asynchronous operations on computed are invalid.
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
Copy the code
Var VM = new Vue({el: '#example', data: {message: 'Hello'}, computed: {// Getter reversedMessage for computed properties: Return this.message.split(" ").reverse().join(" ")}}})Copy the code
Running result:
Original message: "Hello"
Computed reversed message: "olleH"
Copy the code
Note: “reversedMessage” cannot define the same name for the components props, data, and methods, otherwise an error will be reported.
The reason why we recommend using computed on the page is that in the Vue template {{interpolation}} it is convenient to write some simple JS expressions such as {{this.message.split(“).reverse().join(“)}}, Using too much declarative logic in a template can make the template too heavy, especially when using a large number of complex logical expressions to process data on the page, which is what Computed is designed to solve.
1.2 Application Scenarios
- Suitable for some repetitive data or complex and time-consuming operations. We can put it in computed, and then it will be cached on computed, and then we can get it directly next time.
- If we need data that depends on other data, we can make the data computed.
1.3 Usage of GET and set
The above application scenario refers to the actual getter and setter methods for computed,
Data: {message: 'Hello'}, computed: {reversedMessage: {get: Return this.message.split(").reverse().join(")}, set: return this.message.split(").reverse().join(")}, set: Function (val){this.firstName = val.toupperCase (); this.firstName = val.toupperCase (); }}}Copy the code
1.4 Differences between Computed and Methods?
< div id = "app" > < p > the original data: {{MSG}} < / p > < p > after the inversion data for: {{ reversedMsg() }}</p> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: /* computed: {reversedMsg() {return this.msg. Split (").reverse().join(")}} */ methods: Return this.msg. Split (" ").reverse().join(" ")}}}); console.log(vm); </script>Copy the code
In the code above, the method reversedMsg() is called in the template with our reversed data; This method is also defined in methods. The same effect can be achieved, so what’s the difference between them?
- Computed is cached based on responsiveness dependencies. They are reevaluated only if the responsive dependencies change, that is, if the value of the MSG property has not changed, multiple visits to the reversedMsg computation property will immediately return the cached results, rather than executing the functions in computed again. But in the methods method, every time it’s called, it’s going to execute the function, it’s not reactive.
- A computed member can have only one function defined as a read-only attribute or a get/set attribute that can be read and write, but the methods member does not.
I won’t go into much detail with the following code
<div id="app"> <div> The first time a computed attribute is invoked: {{reversedMsg}}</div> <div> The second time a computed attribute is invoked: {{reversedMsg}}</div> <div> The third time that a computed attribute is invoked: {{reversedMsg}}</div> <! {{reversedMsg1()}}</div> <div> {{reversedMsg1()}}< div> {{ reversedMsg1() }}</div> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: 'hello' }, computed: { reversedMsg() { console.log(1111); Return this.msg.split(" ").reverse().join(" ")}}, methods: {reversedMsg1() {console.log(2222); / / this point to return the vm instance. This MSG. The split (' '). Reverse () join (' ')}}}); console.log(vm); </script>Copy the code
What are the benefits of using computed?
In the code above you can see that on computed you have the property reversedMsg, and then in that method it prints 1111; The information comes out, the method in the methods reversedMsg1 will also print out 2222 information, but in computed, except for the first time, The reversedMsg function will not be executed again. But in methods, there is no caching, and every time the reversedMsg1() method is executed, the information is printed.
So now let’s understand what caching does. Why does computed require caching? We all know that our HTTP also has a cache, and for some static resources, our NGINx server caches our static resources, If nothing has changed, the static resource will be read directly from the cache, so that the server will not have to re-request the data, which avoids some undaunted requests, improves access speed, and optimizes the user experience.
The same is true for us for computed. As shown in the above code, we called the reversedMsg method on computed three times. If we had hundreds or thousands of calls, it would be wasteful to calculate each call if the dependent data had not changed. So computed is designed to optimize for that.
2. Watch: monitoring
2.1 Definition of watch
Watch is a listening action. Watch is used to monitor (the number of data in the data) changes and calls the function. NewVal is used to get the new value of the argument, and oldVal is used to get the old value of the argument.
- Watch is a listener, can listen to a certain data, and then perform the corresponding operation;
- Does not support caching, data changes will directly trigger the corresponding operation;
- The listening function takes two arguments, the first of which is the latest value; The second parameter is the value before the input;
- With support for asynchronous operations, Watch is more efficient when performing asynchronous or expensive operations when data changes. ;
<div id="app"> {{count}} {{result}} <button type="button" @click="addbtnfn(2)" > </button> </div> <script SRC = "https://cdn.bootcss.com/vue/2.6.10/vue.js" > < / script > < script > new Vue ({el: '# app, data: {count: 0, the result is:'}, methods:{ addbtnfn:function(step){ this.count+=step; // this.result=newVal>10?" }}, watch:{count:function(newVal,oldVal){this.result=newVal>10?" > 10":" < 10"}}}); </script>Copy the code
2.2 Application Scenarios
- Use watch if a piece of data needs to be listened on and something done to it
- When a value changes, will cause a series of operations, this case is suitable for use of watch;
2.3 Listening data Types
2.3.1 Listening for simple data types
data:{
'first':2
},
watch:{
first:function(){
console.log(this.first)
}
}
Copy the code
2.3.2 Listening for Complex Data Types
data:{
'first':{
second:0
}
},
watch:{
first:{
handler:function(oldVal,newVal){
console.log(oldVal)
console.log(newVal)
},
deep:true
}
}
Copy the code
2.3.3 Listening for a Single Attribute of an Object
- Method one: you can use the object directly. Property method to get the property
data:{ 'first':{ second:0 } }, watch:{ 'first.second':function(newVal,oldVal){ console.log(newVal,oldVal); }}Copy the code
- Method 2: Watch If you want to monitor the changes of a single attribute of an object, use computed as the middleware to transform the object, because computed can obtain the corresponding attribute value
data:{ 'first':{ second:0 } }, computed:{ secondChange:function(){ return this.first.second } }, Watch :{secondChange:function(){console.log('second attribute value changed ')}}Copy the code
2.4 Differences between computed and Watch
- ** The same: ** Computed and Watch are used to monitor/rely on a data and process it.
- Similarities and Differences: Both are vUE implementations of listeners, but computed is used to process synchronized data, while watch is used to observe a change in a value to complete a complex piece of expensive business logic. Use computed first when available, avoiding the embarrassing situation of calling watch multiple times when multiple data affects one of the data.
2.5 Advanced usage of watch
2.5.1 Handler methods and immediate attributes
<div id="demo">{{ fullName }}</div> <script> var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: Function (val) {console.log(' not executed the first time ~ ') this.fullname = val + '+ this.lastname}}}); </script>Copy the code
Code analysis: As you can see, watch does not execute during initialization. In the example above, the listener is only evaluated when the value of firstName changes. But what if you want to do it the first time it’s bound? This is where we change our example :(improve code)
watch: { firstName: {handler:function(val) {console.log(' first time ~ ') this.fullname = val + '+ this.lastname}, "FirstName" = "firstName"; "handler" = "firstName";Copy the code
Open the console and you can see that ‘first execution ~’ is printed. “FirstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”, “firstName”.
Immediate :true indicates that if firstName is declared in wacth, the handler method in wacth will be executed immediately. If it is false, the handler method will be executed immediately. Why add the handler method and immediate:true to execute the first time at binding time? You’ll see when you analyze the source code.
2.5.2 deep attribute
Watch also has a “deep” property that indicates whether deep listening is enabled. The default value is false.
<div id="app">
<div>obj.a: {{obj.a}}</div>
<input type="text" v-model="obj.a">
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
obj: {
a: 1
}
},
watch: {
obj: {
handler:function(val) {
console.log('obj.a changed')
},
immediate: true
}
}
})
</script>
Copy the code
When we enter data in the input input box to change the value of obj.a, we find that ‘obj.a changed’ is not printed in the console. Due to the limitations of modern JavaScript (and the deprecation of object.Observe), Vue cannot detect the addition or removal of Object properties. Since Vue performs a getter/setter transformation on the property when initializing the instance, the property must be present on the data object for Vue to transform it in order for it to be responsive.
By default, handler methods only listen for references to obj. We only listen for references to obj when we assign a value to it. For example, we reassign obj in the Mounted event hook function:
mounted:function() {
this.obj = {
a: '123'
}
}
Copy the code
Note: This handler will execute and print ‘obj.a changed’.
But what if we need to listen for the value of the property in obj? This is where the deep property comes in. We just need to add deep:true to listen for the value of the property in obj.
Watch: {obj: {handler:function(val) {console.log('obj. A changed')}, immediate: true, deep: true}}Copy the code
The deep property means a deep traversal, traversing the object down the layers (consuming resources), adding listeners at each layer. Reflected in the source is defined in SRC/core/observer/traverse by js: (improve code)
watch: {
'obj.a': {
handler:function(val) {
console.log('obj.a changed')
},
immediate: true
// deep: true
}
}
Copy the code
Personal recommendation: Do not set a listener function for the ‘obj.a’ property until it is encountered to improve performance.
Reference article: