本书在2.2节中提到过计算属性,它是Vue实例的一个选项。在项目开发时,对于简单的计算,可以在模板语法中直接进行计算,但当计算的表达式过于复杂时,就会使模板代码的可读性变差,从而难以维护。为此,Vue.js提供了专门的计算属性。使用计算属性可以将复杂的逻辑放在computed选项中进行处理。
下面通过一个实例来进一步学习计算属性的使用,代码如下。
<style type="text/css"> table.gridtable { font-family: verdana,arial,sans-serif; font-size:11px; color:#333333; border-width: 1px; border-color: #666666; border-collapse: collapse; } table.gridtable th { border-width: 1px; padding: 8px; border-style: solid; border-color: #666666; background-color: #dedede; } table.gridtable td { border-width: 1px; padding: 8px; border-style: solid; border-color: #666666; background-color: #ffffff; } </style> </head> <body> <div id="app"> <table class="gridtable"> <tr><th>学科</th> <th>分数</th> </tr> <tr><td>语文</td> <td><input type="text" name="" id="" v-model.number="chinese" /></td> </tr> <tr> <td>数学</td> <td><input type="text" name="" id="" v-model.number="math" /></td> </tr> <tr><td>英语</td> <td><input type="text" name="" id="" v-model.number="english" /></td> </tr> <tr><td>总分</td> <td><input type="text" name="" id="" v-model.number="sum" /></td> </tr> <tr><td>平均分</td> <td><input type="text" name="" id="" v-model.number="average" /></td> </tr> </table> </div> <script type="text/javascript"> new Vue({ el:'#app', data:{ chinese:90, math:80, english:90, }, computed:{ sum:function(){ return this.chinese+this.math+this.english; }, average:function(){ return Math.round(this.sum/3); } } }) </script> </body> </html>
修改前后,实例在浏览器中的显示效果如图2-13和图2-14所示。只要用户修改任一科目的分数,总分和平均分就会同步改变。
图2-13 修改前,实例在浏览器中的显示效果
图2-14 修改后,实例在浏览器中的显示效果
提示 代码中使用的v-model.number涉及指令的修饰符,目的是确保输入的数值方便sum的计算。指令的修饰符会在第3章中进行详细讲解。如果不使用修饰符,则在使用sum的方法中需要进行数据转换。
计算属性本质上是一个方法,但是通常被当作属性来使用,一般不加(),这样就不能传参。但在实际开发中,如果需要给计算属性中的方法传参,就需要使用闭包传参的方法,代码如下。
<div id="app"> <div>{{ count(5) }}</div> </div> <script src="js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: 'helo world!', num: 10, }, computed: { count() { return function(index) {/必须返回带有参数的函数 return index + 1 } } } }); </script>
上述代码使用count方法传送了一个参数5,计算后,页面渲染出来的效果是数字6。如果要给计算属性中的方法传参,那么方法中必须返回带有参数的函数,computed选项的count()中不能写参数。计算属性是通过闭包传参的方式进行传参的。
计算属性通常用来获取数据(根据data的变化而变化),所以其默认只有getter,但需要时,Vue.js也提供了setter功能,代码如下。
<div id="app"> firstName:<input type="text" name="" id="" value="" v-model="firstName" /> lastName:<input type="text" name="" id="" value="" v-model="lastName" /><br> <p>fullName:<input type="text" name="" id="" value="" v-model="fullName" /></p> </div> <script src="./js/vue.js"></script> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { firstName: 'Jack', lastName: 'Jones', }, computed: { fulName: { // getter get: function() { return this.firstName + '+ this.lastName }, // setter set: function(newValue) { var names = newValue.split(' ) this.firstName = names[0] this.lastName = names[names.length - 1] } } } }) </script>
在上述代码中,计算属性包含了两个函数,分别是get和set。get函数用来获取data中的数据,将data中的字符串数据合并后显示在文本框中,函数没有参数。set函数用来将合并后的数据以空格分开,并分别赋值给data中的firstName和lastName,函数有参数。计算属性的getter和setter在浏览器中的显示效果如图2-15和图2-16所示。
图2-15 计算属性的getter在浏览器中的显示效果
图2-16 计算属性的setter在浏览器中的显示效果
从2.4.1节的计算属性的代码中能够发现,Vue选项中的methods也可以完成计算功能,与计算属性的作用相同。那么,为什么要使用计算属性呢?使用计算属性和使用methods有什么区别呢?因为计算属性是基于它的依赖缓存的,所以只有当其依赖的数据发生变化时,才会重新求值。这就意味着,只要依赖的数据还没有发生改变,多次访问计算属性就会立即返回之前的计算结果,不必再次执行函数,而methods每调用一次就执行一次函数。下面通过一个实例来对比使用计算属性和使用methods的区别,代码如下。
<div id="app"> <h3>顾客你好!</h3> <p> 你购买的手机品牌是{{company}}<br />单价是{{price}}元<br /> 数量是{{count}}部<br />总价是{{total()}}元 </p> </div> <script type="text/javascript"> new Vue({ el: '#app', data: { company: '华为', price: 2000, count: 10, }, methods: { total: function() { console.log('counted') return this.price * this.count; }, } }) </script>
在上述代码中,将total定义为一个方法,也可以实现和计算属性相同的计算功能。不同的是,当频繁访问total的时候,如果price和count的值没有发生变化,则计算属性会立即返回缓存的计算结果,且不会再次执行函数,只有当计算属性的依赖发生变化时,代码才会被再次执行,而methods每访问一次就执行一次函数。使用计算属性和methods后,控制台的输出效果如图2-17和图2-18所示。
图2-17 使用计算属性后,控制台的输出效果
图2-18 使用methods后,控制台的输出效果
使用计算属性的这种方式可以确保代码只在必要的时刻执行,适合处理一些潜在的资源密集型工作。但是,如果项目不具有缓存功能,则要使用methods。所以,是使用计算属性还是使用methods,要根据实际情况而定。现将计算属性的特点总结如下。
(1)当计算属性依赖的数据发生了变化时,会立即进行计算,并对计算结果进行自动更新。
(2)计算属性的求值结果会被缓存起来,以方便下次直接使用。
(3)计算属性适用于执行更加复杂的表达式,这些表达式往往太长或者需要频繁地重复使用,所以不能在模板中直接使用。
(4)计算属性是data对象的一个扩展和增强版本。