Explain Vue calculation attribute and listening attribute in detail

  Front end, html, javascript, node.js, Programmer

Preface

Some beginners may be puzzled by the usage scenarios of computation attributes and listening attributes. This article mainly introduces the usage, usage scenarios and the differences between the two.
Please stamp the code of this articleGithub blog, the paper finally feel shallow, everyone began to knock more code!

Calculation attribute

Introduction

The calculation attribute is to automatically monitor the change of the dependent value, thus dynamically returning the content. Monitoring is a process. When the monitored value changes, a callback can be triggered and some things can be done. It has the following characteristics:

  • Data can be processed logically to reduce calculation logic in templates.
  • Monitor data in calculated attributes
  • Rely on fixed data types (responsive data)

The calculation attribute consists of two parts: get and set, which are used to obtain the calculation attribute and set the calculation attribute respectively. The default is only get. If set is needed, add it yourself. In addition, set sets the attribute, not directly modifying the calculation attribute, but modifying its dependency.

computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      //this.fullName = newValue 这种写法会报错
      var names = newValue.split(' ')
      this.firstName = names[0]//对它的依赖进行赋值
      this.lastName = names[names.length - 1]
    }
  }
}

When running vm.fullName = ‘John Doe’ again now, setter will be called and vm.firstName and vm.lastName will be updated accordingly.

2. Calculation Attribute vs Common Attribute

It is possible to bind calculation attributes in the template just like binding common attributes. There is a difference in definition: the attribute value of calculation attributes must be a function.

data:{ //普通属性
  msg:'浪里行舟',
},
computed:{ //计算属性
  msg2:function(){ //该函数必须有返回值,用来获取属性,称为get函数
    return '浪里行舟';
  },
  reverseMsg:function(){
  //可以包含逻辑处理操作,同时reverseMsg依赖于msg,一旦msg发生变化,reverseMsg也会跟着变化
    return this.msg.split(' ').reverse().join(' ');
 }
}  

3. Calculating Attribute vs Method

The main difference between the two is that computed can be cached and methods cannot be cached.As long as the correlation dependency does not change, the value obtained by accessing the calculation attribute multiple times is the previously cached calculation result and will not be executed multiple times.There is a saying on the Internet that methods can pass parameters, but computational attributes cannot, in fact, are not accurate. Computational attributes can pass parameters through closures:

:data="closure(item, itemName, blablaParams)"
computed: {
 closure () {
   return function (a, b, c) {
        /** do something */
        return data
    }
 }
}

Listening attribute

Vue provides a more general way to observe and respond to data changes on Vue instances: the listening attribute watch.Any logic can be executed in watch, such as function throttling, Ajax asynchronous data acquisition, and even DOM operation (not recommended).

1. General usage

<template>
  <div class="attr">
    <h1>watch属性</h1>
    <h2>{{ $data }}</h2>
    <button @click="() => (a += 1)">修改a的值</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      a: 1,
      b: { c: 2, d: 3 },
      e: {
        f: {
          g: 4
        }
      },
      h: []
    };
  },
  watch: {
    a: function(val, oldVal) {
      this.b.c += 1;
    },
    "b.c": function(val, oldVal) {
      this.b.d += 1;
    },
    "b.d": function(val, oldVal) {
      this.e.f.g += 1;
    },
    e: {
      handler: function(val, oldVal) {
        this.h.push("浪里行舟");
      },
      deep: true //用于监听e对象内部值的变化
    }
  }
};
</script>

watch.gif

2. Use the watch’s depth traversal and immediate call function

When using watch to monitor data changes, in addition to the handler callback, it actually has two parameters, namely:

  • Deep is set to true to listen for changes in the object’s internal values
  • Setting immediate to true will immediately trigger a callback with the current value of the expression
<template>
    <button @click="obj.a = 2">修改</button>
</template>
<script>
export default {
    data() {
        return {
            obj: {
                a: 1,
            }
        }
    },
    watch: {
        obj: {
            handler: function(newVal, oldVal) {
                console.log(newVal); 
            },
            deep: true,
            immediate: true 
        }
    }
}
</script>

In the above code, we have modified the value of the A attribute in the obj object, and we can trigger the handler callback in its watch to output a new object. If deep: true is not added, we can only listen for changes in the obj and will not trigger the callback. At the same time, we have also added the immediate: true configuration, which will immediately trigger the callback with the current value of obj.
Let’s look at another scene that we often encounter in actual work: when the component is created, we get the data of the list once, at the same time we listen to the input box, and we get the filtered list again whenever there is a change.

created(){
    this.fetchPostList()
},
watch: {
    searchInputValue(){
        this.fetchPostList()
    }
}

Is there any way to optimize it?

watch: {
    searchInputValue:{
        handler: 'fetchPostList',
        immediate: true
    }
}

First, in watchers, the literal name of the function can be used directly. Second, declaring immediate:true means that the component is executed immediately when it is created.

The contrast between the two

image.png

From the above flowchart, we can see the difference between them:

  • Watch: What is monitored is the attribute value. Whenever the attribute value changes, it will trigger the execution of a callback function to perform a series of operations.
  • Computed: The monitoring is dependent value. If the dependent value is unchanged, it will directly read the cache for reuse, and will be recalculated if it changes.

In addition, a little important difference is:Calculation properties cannot perform asynchronous tasks; calculation properties must be performed synchronously. In other words, the calculation attribute cannot request or execute asynchronous tasks from the server. If you encounter an asynchronous task, give it to the listening attribute. Watch can also detect the computed attribute.

Next, let’s look at an example of using watch to achieve anti-shake: the view will not be updated until the user stops inputting for more than 1 second.

<template>
  <div>
    {{ fullName }}
    <div>firstName: <input v-model="firstName" /></div>
    <div>lastName: <input v-model="lastName" /></div>
  </div>
</template>
<script>
import { setTimeout } from "timers";
export default {
  data: function() {
    return {
      firstName: "浪里行舟",
      lastName: "前端工匠",
      fullName: "浪里行舟 前端工匠"
    };
  },
  watch: {
    firstName: function(val) {
      clearTimeout(this.firstTimeout);
      this.firstTimeOut = setTimeout(() => {
        this.fullName = val + " " + this.lastName;
      }, 1000);
    },
    lastName: function(val) {
      clearTimeout(this.lastTimeout);
      this.lastTimeOut = setTimeout(() => {
        this.fullName = this.firstName + " " + val;
      }, 1000);
    }
  }
};

watch1.gif

Summary

Computational attributes are suitable for template rendering. A certain value is calculated by relying on other responsive objects or even computational attributes. The listening attribute is suitable for observing the change of a certain value to complete a complex business logic.

  • What computed can do, watch can do, and vice versa
  • Computed as much as possible

Welcome to pay attention to the public number:Front end craftsmanWe witness your growth together!
image

Reference material