Vue.js之计算属性computed

计算属性

在模板中使用表达式是很便利。但是,在模板中放入太多的逻辑会让模板过重而难以维护。例如:

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

 这里,我们必须看一会儿才明白,这里要显示变量message的翻转字符串。当模板中出现多处翻转字符串时,会变得更加难以维护。

所以,对任何复杂逻辑,都应该使用计算属性

基础例子

我们把上面的例子用计算属性来表示。

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})

 结果如下:

Original message: "Hello"

Computed reversed message: "olleH"

这里我们声明了一个计算属性 reversedMessage

说明

  • 可以像绑定普通的property 一样在模板中绑定计算属性。
  • 因为,这里reversedMessage依赖message,所以当vm.message发生改变时,所依赖的vm.reversedMessage也发生改变。
  • 计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。

计算属性缓存VS方法

当然,你应该注意到了,使用函数能够达到同样的效果(事实上,在此之前,我确实更习惯函数)。

<p>Reversed message: "{{ reversedMessage() }}"</p>
// 在组件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

这两种方法,返回的结果是完全一样的。不同点在于:计算属性是依据它的响应式依赖进行缓存的。只有响应式的依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数什么意思?

函数

已知a = 3 。函数b返回 a + 3的值。

问: 函数b等于多少?

答:b = 3 + 3 = 6。

问:函数b等于多少?

答:b = 3 + 3 = 6。

……

现在a = 5了。

问题:函数b等于 多少?

答:b = 5+3 = 8。

问题:函数b等于 多少?

答:b = 5+3 = 8。

……

计算属性

已知a = 3 。计算属性b返回 a + 3的值。也就是b = 3 + 3 = 6。

问: 计算属性b等于多少?

答: b = 6。

问:计算属性b等于多少?

答:b= 6。

……

现在a = 5了。所以计算属性b = 5+ 3 = 8。

问题:计算属性b等于多少?

答:b=8。

问题:计算属性b多少?

答:b = 8。

……

可以看到,如果方法计算的方法复杂,又多次调用可以节约多少开销。

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

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

计算属性VS监听属性

Vue提供了另一种更通用的方法来响应Vue实例上的数据变动:监听属性。当我们需要数据变动的时候,很容易滥用watch——特别是之前使用Angular.js的时候。比如,这里计算全名的方法。

<div id="demo">{{ fullName }}</div>
 1 var vm = new Vue({
 2   el: '#demo',
 3   data: {
 4     firstName: 'Foo',
 5     lastName: 'Bar',
 6     fullName: 'Foo Bar'
 7   },
 8   watch: {
 9     firstName: function (val) {
10       this.fullName = val + ' ' + this.lastName
11     },
12     lastName: function (val) {
13       this.fullName = this.firstName + ' ' + val
14     }
15   }
16 })

上面的代码是命令式的且重复的。现在,我们用计算属性的版本:

 1 var vm = new Vue({
 2   el: '#demo',
 3   data: {
 4     firstName: 'Foo',
 5     lastName: 'Bar'
 6   },
 7   computed: {
 8     fullName: function () {
 9       return this.firstName + ' ' + this.lastName
10     }
11   }
12 })

 是不是看起来好多了呢?

计算属性的setter

计算属性默认只提供getter,当然,根据需要也可以提供setter。

 1 // ...
 2 computed: {
 3   fullName: {
 4     // getter
 5     get: function () {
 6       return this.firstName + ' ' + this.lastName
 7     },
 8     // setter
 9     set: function (newValue) {
10       var names = newValue.split(' ')
11       this.firstName = names[0]
12       this.lastName = names[names.length - 1]
13     }
14   }
15 }
16 // ...

 现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName vm.lastName 也会相应地被更新。

参考网址

https://cn.vuejs.org/v2/guide/computed.html#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7

posted @ 2021-07-24 17:44  陆陆无为而治者  阅读(232)  评论(0编辑  收藏  举报