The difference between computed and watch in Vue and detailed application scenarios

In Vue projects, we often need to deal with data changes. At this time, we need to use the two attributes of watch and computed. Since they are all attributes that trigger changes in values, what are the similarities and differences between them?

1. Calculated attributes

Features:

  1. Support caching, only when the dependent data changes, will the calculation be re-calculated;
  2. Asynchronous is not supported. It is invalid when there is an asynchronous operation in the computed, and it is impossible to monitor data changes;
  3. The computed attribute values ​​will be cached by default, and the computed attributes are cached based on their responsive dependencies. That is, the value calculated based on the data in the props declared in the data or passed by the parent component;
  4. If an attribute is calculated from other attributes, this attribute depends on other attributes is a many-to-one or one-to-one, generally calculated;
  5. If the computed property value is a function, then the get method will be taken by default, and the return value of the function is the property value of the property; in the computed property, the property has a get and a set method. When the data changes, the set method is called;
<template>
  <div>
    <el-input v-model="firstText"></el-input>
    <el-input v-model="lastText"></el-input>
    <el-input v-model="mergeText1"></el-input>
    <el-input v-model="mergeText2"></el-input>
  </div>
</template>

<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      firstText:'hello',
      lastText:'world',
    };
  },
  computed:{
    
    
    mergeText1(){
    
    
      return this.firstText + ' ' + this.lastText;
    },
    mergeText2:{
    
      /* 通过mergeText2反向赋值给 firstText和lastText */
      // getter
      get() {
    
      // 回调函数 当需要读取当前属性值是执行,根据相关数据计算并返回当前属性的值
        return `${
      
      this.firstText} ${
      
      this.lastText}`;
      },
      // setter
      set(val) {
    
      //监视当前属性值的变化,当属性值发生变化时执行,更新相关的属性数据,val就是fullName的最新属性值
        const names = val.split(' ');
        console.log(names);
        this.firstText = names[0];
        this.lastText = names[names.length - 1];
      }
    }
  },
};
</script>

advantage:

  1. When the value of the data variable is changed, the entire application will be re-rendered, and Vue will be re-rendered to the dom by the data. At this time, if we use names, the method will be called with rendering, and computed will not be recalculated, so the performance overhead is relatively small. When the new value needs a lot of calculations to get, the meaning of caching is very big;
  2. If the calculated data changes, the calculated properties will be recalculated and cached; when other data is changed, the calculated properties will not be recalculated, thereby improving performance;
  3. When the obtained value needs to be processed and used, you can use computed;

Application scenarios:
Insert picture description here

2. Listener attribute watch

Features:

  1. Does not support caching, data changes will directly trigger the corresponding operation;
  2. watch supports asynchronous operation;
  3. The listening function receives two parameters, the first parameter is the latest value; the second parameter is the value before the input;
  4. When an attribute changes, the corresponding operation needs to be performed, one-to-many;
  5. The monitoring data must be the data in the props declared in data or passed from the parent component. When the data changes to trigger other operations, the function has two parameters:
    immediate: component loading immediately triggers the execution of the callback function;
    deep: deep monitoring; in order to find changes in the internal value of the object, it is used when complex types of data, such as the object in the array For content changes, note: you don't need to do this to monitor changes in the array. Note: Deep cannot monitor the changes of the array and the addition of objects. Refer to the Vue array mutation. Only when triggered in a responsive manner will it be monitored;

Note: This method is most useful when you need to perform asynchronous or expensive operations when the data changes. This is the biggest difference from computed.

2.1 General usage, monitor a single variable or an array

<template>
  <div>
    <el-input v-model="firstText"></el-input>
    <el-input v-model="lastText"></el-input>
    <el-input v-model="mergeText"></el-input>
  </div>
</template>

<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      firstText:'hello',
      lastText:'world',
      mergeText:'',
    };
  },
  watch:{
    
    
    // 监听当firstText的值变化,触发此事件,改变mergeText的值
    firstText(newText,oldText){
    
    
      console.log(newText, oldText);
      this.mergeText = newText + ' ' + this.lastText;
    }
  },
};
</script>

2.2 Monitoring simple data types

<template>
  <div>
    <el-input v-model="mergeText"></el-input>
  </div>
</template>

<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      mergeText:'',
    };
  },
  watch:{
    
    
    // mergeText值变化即触发
    mergeText(newval,oldVal){
    
    
      console.log(this.mergeText,newval,oldVal);
    }
  },
};
</script>

2.3 Monitoring complex data (deep monitoring)

When deep is not used, when we change the value of obj.a, watch cannot monitor data changes. By default, the handler only monitors the changes of attribute references, that is, only one layer is monitored, but the internal attributes of the object are changed. Less than.

immerdiate attribute: By declaring the immediate option as true, the handler can be executed immediately.

<template>
  <div>
    <el-input v-model="obj.text"></el-input>
  </div>
</template>

<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      obj:{
    
    
        text:'hello'
      }
    };
  },
  watch:{
    
    
    // 监听对象obj的变化
    obj:{
    
    
      handler (newVal,oldval) {
    
    
        console.log(newVal,oldval)
      },
      deep: true,
      immediate: true
    }
  },
};
</script>

By using deep: true for in-depth observation, we listen to obj, we will traverse the attributes layer by layer under obj, and add monitoring events. This will increase the performance overhead. As long as any attribute value in obj is modified, the handler will be triggered. So how to optimize performance?
You can directly use the object. Property method to get the property

<template>
  <div>
    <el-input v-model="obj.text"></el-input>
  </div>
</template>

<script>
export default {
    
    
  data() {
    
    
    return {
    
    
      obj:{
    
    
        text:'hello',
      }
    };
  },
  watch:{
    
    
    // 监听对象单个属性text
    'obj.text':{
    
    
      handler (newVal,oldval) {
    
    
        console.log(newVal,oldval)
      },
      immediate: true, // 该属性会先执行一次handler
    }
  },
};
</script>

Precautions:

  1. The function name in watch must be the attribute name in the dependent data;
  2. The function in watch does not need to be called, as long as the attribute on which the function depends is changed, the corresponding function will be executed;
  3. The function in watch will have two parameters, one is the new value and the other is the old value;
  4. By default, watch cannot monitor the changes of the object. If you need to monitor, you need to monitor deeply. You need to configure the handler function and deep to true. (Because it will only monitor whether the address of the object has changed, and the value will not be monitored);
  5. By default, watch will not do the monitoring the first time. If you need to do the monitoring during the first loading, you need to set immediate: true;
  6. In special cases, watch cannot monitor the changes of the array:
    use subscripts to change the data in the array;
    use length to change the length of the array;
    solution:
通过 Vue 实例方法 set 进行设置 $set( target, propertyName/index, value);
参数:target {
    
    Object | Array} , propertyName/index {
    
    string | number}, value {
    
    any}

this.$set(this.arr,0,100);
通过 splice 来数组清空 $delete( target, propertyName/index )
参数:target {
    
    Object | Array} , propertyName/index {
    
    string | number}

this.$delete(this.arr,0)
  1. The function name corresponding to the in-depth monitoring must be handler, otherwise it will have no effect, because the watcher corresponds to the call to the handler

Application scenarios:
Insert picture description here

3. Methods

The methods are different from the previous ones. We usually write the methods here. As long as they are called, they will be executed again. Correspondingly, there are some trigger conditions. In some cases, the specific difference between methods and computed cannot be seen, but once the amount of calculation is The more complex pages will reflect the difference.

Note: Computed is cached, which means that as long as the dependency of the calculated attribute does not update the corresponding data, then the computed will directly get the value from the cache, and multiple visits will return the previous calculation result.

4. Summary

In terms of computed and watch, one is calculation and the other is observation, which is semantically different.
Calculation is to obtain data through variable calculations, and observation is to observe a specific value, and make corresponding changes according to the changes of the observer. It cannot be mixed with each other in a specific scenario, so it is still necessary to pay attention to the rationality and semantics of the use of api .

Guess you like

Origin blog.csdn.net/ZYS10000/article/details/114048457