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