A, problem,

The project came across someone writing code in computed like this:

computed: {
  getName() {
    return function () {
      return "Zhang"; }; }},Copy the code

This code looks fine, but in fact it undermines the purpose of computed, which is to simplify long, smelly computing logic in templates, to make template code look cleaner and easier to maintain, and to optimize performance by caching computed properties based on responsive dependencies.

2. Introduction to computing attributes

The official description of calculated attributes is as follows:

Document address: cn.vuejs.org/v2/guide/co…

Why does this code violate the purpose of computed?

Take a look at the difference between computed and methods, and then we can explain the problem. The official description is as follows:

Documents: cn.vuejs.org/v2/guide/co…

That is to say, although both have the same effect, computed caching is based on responsive dependency, whereas methods does not. Let’s verify that:

Three, practice test

First create computed and Methods, print the log, and then call each of them a few times on the page

<template>
  <div>
    <p>{{ computed_getName }}</p>
    <p>{{ computed_getName }}</p>
    <p>{{ computed_getName }}</p>
    <p>{{ computed_getName }}</p>

    <p>{{ method_getName() }}</p>
    <p>{{ method_getName() }}</p>
    <p>{{ method_getName() }}</p>
    <p>{{ method_getName() }}</p>
  </div>
</template>

<script>
export default {
  computed: {
    computed_getName() {
      console.log("Computed attribute invoked");
      return "Zhang"; }},methods: {
    method_getName() {
      console.log("Methods are called");
      return "Bill"; ,}}};</script>
Copy the code

The page running result is as follows:

The console output is as follows:

As a result, you can see that although both the computed_getName attribute and the method method_getName are referenced four times in the template, computed_getName is fired only once and the method method_getName is fired four times, This verifies that computed has a caching function.

What if I changed the calculation property to the return function I mentioned at the beginning?

<template>
  <div>
    <! The corresponding call calculation property should also be changed to the form of a function.
    <p>{{ computed_getName() }}</p>
    <p>{{ computed_getName() }}</p>
    <p>{{ computed_getName() }}</p>
    <p>{{ computed_getName() }}</p>

    <p>{{ method_getName() }}</p>
    <p>{{ method_getName() }}</p>
    <p>{{ method_getName() }}</p>
    <p>{{ method_getName() }}</p>
  </div>
</template>

<script>
export default {
  computed: {
    computed_getName() {
      // Change it to a return function
      return function () {
        console.log("Computed attribute invoked");
        return "Zhang"; }; }},methods: {
    method_getName() {
      console.log("Methods are called");
      return "Bill"; ,}}};</script>
Copy the code

The page running result is as follows:

The console output is as follows:

It turns out that, after the return function, you have to call the computed function (the same as calling a method, except that the method is defined in a computed location) to get the computed result, so it loses its role as a cache.

Why do we need caching? Suppose we have A computationally expensive property, A, that iterates through A large array and does A lot of computations. And then we might have other computational properties that depend on A. Without caching, we would inevitably execute A’s getter multiple times! If you don’t want caching, use methods instead.

So, assuming that getName in this example was an expensive calculation property and now it has lost its caching function, can we follow the official convention and use it instead?

Another reason is that the creation steps of a calculated attribute are more complex, so you can refer to the following article to learn (rather lazy, there are ready-made paste this, light Sprite…). :

Cloud.tencent.com/developer/a…

And the creation of a method is relatively simple, the source code is as follows:

To get rid of this whole bunch of fault tolerant judgments, you would simply iterate through all the methods and mount them to the instance VM as follows:

function initMethods (vm, methods) {
  var props = vm.$options.props;
  for (var key in methods) {
    // omit other code
    vm[key] = typeofmethods[key] ! = ='function'? noop : bind(methods[key], vm); }}Copy the code

Sometimes computations depend on a state in the template data, and you want to pass parameters by returning a function in a computed property, both to optimize memory usage with the help of computed caching and to simplify a lot of computed logic in templates, but that’s a good idea, but you need to be rational about computed data.

So if you see someone else doing something in a computed return function, do you know what to do?

Four,

  • Computing attributes are suitable for simplifying template logic, with caching characteristics, with a good absolute artifact
  • The return function has the same role in evaluating properties as method, but the performance overhead is much higher than method