vue advanced: computed VS watch

Posted by elacdude on Wed, 19 Jan 2022 21:19:42 +0100

Chestnuts

Let's start with an example

<template>
    <div>
        <input type="text" placeholder="Please enter a to-do" @keyup.enter="insertTodo" :value="todo">
        <ul v-for="(todo, i) in todos" :key="i">
            <li>{{ todo }}</li>
        </ul>
        <!-- It's complicated,It is also complex to read, and the readability of the template is very poor,Not elegant enough -->
        <div>To do list:{{ todos.length + 'term' }}</div>
    </div>
</template>

The to-do list is somewhat inelegant. If the expression in the template is more complex, it will look more messy. Putting too much logic in the template will make the template too heavy and difficult to maintain. So for any complex logic. Should use calculated properties. Although the listening attribute can also make the template concise, it is not recommended. The reasons are described below.

Calculation properties:

<template>
    <div>
        <input type="text" placeholder="Please enter a to-do" @keyup.enter="insertTodo" :value="todo">
        <ul v-for="(todo, i) in todos" :key="i">
            <li>{{ todo }}</li>
        </ul>
        <div>To do list:{{ total }}</div>
    </div>
</template>
<script>
export default {
  name: 'Computed',
  data () {
    return {
      todo: '',
      todos: ['Buy vegetables']
    }
  },
  methods: {
    insertTodo (e) {
      if (e.target.value) {
        this.todo = ''
        this.todos.push(e.target.value)
        this.total = 'ha-ha'
      }
    }
  },
  computed: {
    total () {
      return this.todos.length + 'term'
    }
  }
}
</script>

The calculated attribute is an object. The key value in the object is a value that will be inserted into the data response data after declaration. return is the value of the key. The key in calculated is used in the same way as the key in data.

You may ask, why do you want to return in computed? Isn't it the same to set replication directly in method? Compared with method, computed not only can complete business functions, but also has caching. The calculated attributes are cached based on their responsive dependencies. That is, in the above example, as long as the todos that total depends on does not change, the calculation property will immediately return the previous calculation result without re evaluating the function. In contrast, whenever a re rendering is triggered, the calling method will always execute the function again.

Why cache

Why do we need caching? Suppose we have A computing property A with high performance overhead, which needs to traverse A huge array and do A lot of calculations. Then we may have other computational properties that depend on A. If there is no cache, we will inevitably execute A's getter many times! If you don't want to have A cache, use method instead.

Calculate the setter of the property

By default, there is only getter for calculation properties, but you can also provide a setter when necessary:

computed: {
    total: {
      get () {
        return this.todos.length + 'term'
      },
      set (val) {
      	// You can do something here
        console.log('set Lele')
      }
    }
  }

In the above example, if you assign a value to total, you will enter the set function. such as

this.total = 'XXX'
// Will print
"set Lele"

Listener:

Although computed properties are more appropriate in most cases, sometimes a custom listener is required. Vue provides a more general way to respond to changes in data through the watch option.

For example, the above requirements can be completed through watch:

   watch: {
     todos (newVal, oldVal) {
       this.count = newVal.length + 'term'
     }
   },

watch accepts an object. key is the value to monitor and listen. Value is a function with two parameters: the value before change and the value after change of the detected value. Function can do some logical operations that need to be performed after the value is changed.

In the above code, when the todos item is added, you can see that the count will change accordingly, but the first time you come in, the count has no value, because the watch will be triggered only when the detected data changes~
Therefore, in general, it is not recommended to use watch, but to use computed. Use watch only when you need to perform asynchronous or expensive operations when data changes.

How to trigger the watch as soon as it comes in???

Set immediate to true. This configuration means to trigger immediately.
There is another useful option, deep. When our todos is a multi-layer data, such as an object array or a deeper level, we can't monitor its changes. Set true to deeply monitor.

 watch: {
    todos: {
      immediate: true,
      deep: true,
      handler (newVal) {
        this.count = newVal.length + 'term'
      }
    }
  },

computed VS watch

  • The data processing scenarios of the two are different. The monitor is suitable for one data to affect multiple data, and the calculated attribute is suitable for one data to be affected by multiple data
  • The calculated attribute is cached, and the calculated value will not be executed repeatedly if there is no change
  • The listener option provides a more general method for performing asynchronous or expensive operations

Topics: Javascript Front-end Vue.js