一,计算属性
通过前面的学习,我们可以在模板中双向绑定一些数据或表达式了。但是表达式如果过长,或逻辑更为复杂时,就会变得雕肿甚至难以阅读和维护。例如:
<div id="example">{{ message.split('').reverse().join('') }}
</div>
这里是想要显示变量 message 的翻转字符串,为了达到目的。这个表达式包含了三个操作。显然,如果想要在模板中多包含此处的翻转字符串时,就会显得代码相当臃肿。
当一个属性的值依赖于其它属性的值时就可以使用的计算属性
来简化代码。举个例子:
<div id="example"><p>Original message: "{{ message }}"</p><p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
<script src="vue.js" type="text/javascript" charset="UTF-8"></script>
<script>var vm = new Vue({el: '#example',data: {message: 'Hello'},computed: {// 计算属性的 getterreversedMessage: function () {// `this` 指向 vm 实例return this.message.split('').reverse().join('')}}})
</script>
结果如下:
所有的计算属性都以函数的形式写在 Vue 实例内的 comput
选项内,最终返回计算后的结果,即我们可以把一些计算的过程写到一个计算属性——comput
选项内中去,然后让它动态地计算,例如:
二,缓存特性
在上面的例子里,我们完全可以在表达式中调用方法来完成反序操作而不用计算属性,那么为什么还需要计算属性呢?原因就是计算属性是基于它的依赖缓存
的:一个计算属性所依赖的数据发生变化时,它才会重新取值更新,否则只会返回之前的计算结果。
computed: {now: function () {return Date.now()}
}
上面的例子就不会实时更新,因为Date.now()不是响应式依赖。如果是在方法中使用Date.now(),则会在方法被调用时出现更新。
三,计算属性的使用
一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。
1, 使用vue实例内的多个数据
除了上例简单的用法,计算属性还可以依赖Vue实例的多个数据,只要其中任意一个数据变化,计算属性就会重新执行,视图也会更新。
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>学习Vue</title><style type="text/css">#example {color: red;font-size: 20px;}</style></head><body><div id="example"><p>商品总价: {{ totalPrice }}</p></div><script src="vue.js" type="text/javascript" charset="UTF-8"></script><script>var vm = new Vue({el: '#example',data: {package1: [{name: 'iphone12 pro max 128GB',price: 9299,count: 2,},{name: 'xiaomi10 至尊纪念版 8+256',price: 5599,count: 3,}],package2: [{name: 'apple',price: 3,count: 3,},{name: 'millet',price: 12,count: 1,}]},computed: {totalPrice: function () {var price = 0;for (var i=0; i<this.package1.length; i++){price += this.package1[i].price * this.package1[i].count;}for (var i=0; i<this.package2.length; i++){price += this.package2[i].price * this.package2[i].count;}return price;}}})</script></body>
</html>
2,计算属性的getter与setter
每一个计算属性都有getter与setter。
前者用于读取,是默认使用的;
后者用于写入设置,会在修改数据后被触发,通常不使用。
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>学习Vue</title><style type="text/css">#example {color: red;font-size: 20px;}</style></head><body><div id="example"><p>姓名: {{ fullName }}</p></div><script src="vue.js" type="text/javascript" charset="UTF-8"></script><script>var vm = new Vue({el: '#example',data: {first_name: 'Jack',last_name: 'Johnson'},computed: {fullName: {get: function (){return this.first_name + ' ' + this.last_name;},set: function (value){var new_nme = value.split(' ');this.first_name = new_nme[0];this.last_name = new_nme[name.length-1];}}}});vm.fullName = "Vincent van Gogh";</script></body>
</html>
3,跨vue实例使用数据
计算属性除了依赖本vue实例的数据外,还可以依赖其它势力的数据。
<div id="app1"><p>app1's number: "{{ a }}"</p>
</div>
<div id="app2"><p>app2's number: "{{ b }}"</p><p>the computed sum: "{{ sum }}"</p>
</div>
<script src="vue.js" type="text/javascript" charset="UTF-8"></script>
<script>var app1 = new Vue({el: '#app1',data: {a: 1}})var app2 = new Vue({el: '#app2',data: {b: 2},computed: {sum: function () {return app1.a + this.b;}}})
</script>
结果如下:
4,计算属性依赖其它计算属性
除了数据依赖,计算属性也可依赖其它计算属性。
<div id="app"><p>a: "{{ a }}"</p><p>a double: "{{ aDouble }}"</p><p>a plus: "{{ aPlus }}"</p>
</div>
<script src="vue.js" type="text/javascript" charset="UTF-8"></script>
<script>var vm = new Vue({el: '#app',data: {a: 1},computed: {aDouble: function (){return this.a * 2;}, aPlus: {get: function () {return this.a += 4;},set: function (value) {this.a = value - 1;}}}})console.log(vm.a)console.log(vm.aPlus) console.log(vm.aPlus = 3)console.log(vm.a)console.log(vm.aDouble)
</script>
结果如下: