Luna Tech

Tutorials For Dummies.

Vue: Computed Properties

2022-03-19


0. Intro

Reference

Computed property 可以让我们做 data transformation 或者 calculation,减少 template 里面的 logic code,让代码更美观。

注意:

  1. computed property 必须有 return value;
  2. computed property 不能改变 existing data,它只用于 presentation layer(比如我们要用 spread operator 来 clone array);

computed property vs methods

需要改变 data,用 method; 需要改变 presentation of existing data,用 computed property;


1. Example

<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>

上面这个例子就是在 template 里面加了 logic。

推荐使用 computed property when there’s complex logic that includes reactive data.

Refactored

<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
export default {
  data() {
    return {
      author: {
        name: "John Doe",
        books: [
          "Vue 2 - Advanced Guide",
          "Vue 3 - Basic Guide",
          "Vue 4 - The Mystery",
        ],
      },
    };
  },
  computed: {
    // a computed getter
    publishedBooksMessage() {
      // `this` points to the component instance
      return this.author.books.length > 0 ? "Yes" : "No";
    },
  },
};

2. Related Knowledge

Data binding for computed properties

You can data-bind to computed properties in templates just like a normal property. Vue is aware that this.publishedBooksMessage depends on this.author.books, so it will update any bindings that depend on this.publishedBooksMessage when this.author.books changes.

Typing computed properties

Reference


3. Computed caching vs methods

Example of using methods

<p>{{ calculateBooksMessage() }}</p>
// in component
methods: {
  calculateBooksMessage() {
    return this.author.books.length > 0 ? 'Yes' : 'No'
  }
}

区别

Method always run the function whenever a re-render happens.

Computed Properties have caching (效率更高,速度更快,减少无用功):

所以只要 author.books 不变,computed property 就会 return cached value。

Why do we need caching? Imagine we have an expensive computed property list, which requires looping through a huge array and doing a lot of computations. Then we may have other computed properties that in turn depend on list. Without caching, we would be executing list’s getter many more times than necessary! In cases where you do not want caching, use a method call instead.

什么时候不要用 computed property

下面这个例子的 now 永远不会 update,因为 Date.now() 不是一个 reactive dependency。

computed: {
  now() {
    return Date.now()
  }
}

Displaying Filtered/Sorted Results

假如只是 display purpose,那么我们就用 computed properties 来完成。 如果不能用 computed property(比如在 v-for loop 里面),就用 method。

Example 1 - computed property

<li v-for="n in evenNumbers">{{ n }}</li>
data() {
  return {
    numbers: [1, 2, 3, 4, 5]
  }
},
computed: {
  evenNumbers() {
    return this.numbers.filter(n => n % 2 === 0)
  }
}

Example 2 - method

<ul v-for="numbers in sets">
  <li v-for="n in even(numbers)">{{ n }}</li>
</ul>
data() {
  return {
    sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
  }
},
methods: {
  even(numbers) {
    return numbers.filter(number => number % 2 === 0)
  }
}

4. Writable Computed

Computed property 默认是 getter-only,假如你给这个 property assign value 会出现 runtime warning。 假如你需要 writable computed property(在很少的情况下才会这么做),那么你可以创建一个拥有 getter 和 setter 的 property。 在下面的例子中,当你给 fullName 这个 computed property 赋值的时候,就会调用 setter 来 update firstName 和 lastName。

export default {
  data() {
    return {
      firstName: "John",
      lastName: "Doe",
    };
  },
  computed: {
    fullName: {
      // getter
      get() {
        return this.firstName + " " + this.lastName;
      },
      // setter
      set(newValue) {
        // Note: we are using destructuring assignment syntax here.
        [this.firstName, this.lastName] = newValue.split(" ");
      },
    },
  },
};

5. reverse() and sort()

Be careful with reverse() and sort() in a computed property! These two methods will mutate the original array, which should be avoided in computed getters. Create a copy of the original array before calling these methods.

- return numbers.reverse()
+ return [...numbers].reverse()

6. Best Practices

  1. It is important to remember that computed getter functions should only perform pure computation and be free of side effects. No async request or DOM manipulation in computed getter.
  2. 不要改变 computed value,因为它就是个临时的 snapshot,一个 derived value,最好就是 read-only,我们是通过 update computed value 的 source 来改变 computed value 的。