什么是计算属性?
- 我们在模版template中,我们可以使用 {{ }} 这种模版语法来显示一些 data 中的数据的
但是在某些情况下,我们是需要对一些数据进行一些转化后再进行显示,或者将多个数据合并在一起再进行展示,如下:
<div id="app"><h2>{{firstName + ' ' + lastName}}</h2><h2>{{firstName}} {{lastName}}</h2><!-- 如上两种写法都可以实现想要的效果,但是很不好用,很长 --><!-- 我想要用更简单的方法 --><!-- 1.使用方法来进行字符串的拼接 --><h2>{{getFullName()}}</h2><!-- 2.使用计算属性 --><h2>{{fullName}}</h2></div><script>const app = new Vue({el: '#app',data: {message: 'hello',firstName: 'Ryan',lastName: 'Zhang'},computed: {fullName: function() {return this.firstName + ' ' + this.lastName;}},methods: {getFullName: function() {return this.firstName + ' ' + this.lastName;}}})</script>
其实我们也是可以使用methods来进行拼接的,定义一个getFullName方法,在模版字符串中进行方法的调用即可,但是有个问题,这里使用 getFullName() 来进行调用不太合适,因为我们这里想用的是一个变量而不是一个方法,所以就引出了计算属性来解决这个问题
- 计算属性:当我们想要对我们的数据进行某种变化之后再进行显示的话,可以在计算属性中重新定义一个属性,并且返回变化之后的数据
- computed中定义其实也是一个个方法,但是起的名字并不像methods里面的方法一样都是动词开头的(如 getFullName 这种的),computed中的方法起的名字都是一些名词(如 fullName)
- 而且 computed 翻译为 计算属性 ,所以我们尽量按照属性的方式来起名字
- 注意:这里调用计算属性中定义的方法时,是不需要加()的!
- 本质:其实这里的就是一个属性,但是Vue中只实现了它的 get() 方法
计算属性的复杂操作
显示四本书的总价格
<div id="app"><h2>总价格:{{totalPrice}}</h2></div><script>const app = new Vue({el: '#app',data: {books: [{id:110, name: 'Unix编程艺术', price:119},{id:111, name: '代码大全', price:120},{id:112, name: '深入理解计算机原理', price:121},{id:113, name: '现代操作系统', price:122},]},computed: {totalPrice: function() {let result = 0for(let i=0; i<this.books.length; i++) {result += this.books[i] .price}for(let i in this.books) {~~~}for(let book of this.books) {~~~}}}})</script>
计算属性和methods有很大的区别:计算属性在多次调用时只会调用一次,而methods调用几次就会执行几次,是没有缓存的,性能更低地点
计算属性的getter和setter
question1:为什么使用计算属性时,不用加上括号来调用,而是直接使用名称即可?
- 计算属性computed,它是一个对象{ },里面的内容其实就是一个个键值对,比如这里的fullName就是属性名,后面的对象就是属性值
- 只不过这个对象中放的是两个函数,一个是set函数,一个是get函数,分别对应不同的功能
- 我们使用fullName这个属性时,其实就是去调用其内部的 get() 方法
- 计算属性这个东西,一般只需要实现它的 get() 方法就可以了,不用实现 set() 方法,只实现 get() 方法其实就是实现了fullName的只读属性
- 一般我们在使用时,每次都是只写 get() 方法,所以为了简便,Vue就帮我们封装成了这种写法:fullName: function() { ~ }
所以这也就回答了,为什么不用小括号来调用计算属性,fullName不是一个函数,而是一个属性,我们只是使用这个属性名,它其实是内部调用的 get() 方法的!!
const app = new Vue({el: '#app',data: {firstName: 'ryan',lastName: 'zhang'},computed: {fullName: {set: function() {},get: function() {return this.firstName + ' ' + this.lastName}}}})
如果我们想要实现 set() 方法,当data中的值发生变化时(比如直接修改 app.fullName = ‘Kobe Bryant’),这时就会调用 set() 方法,而且一般要给 set() 方法传递一个参数newValue,如下
这时就会打印我们修改后的新值,而且我们最好将这个新值进行处理后,再赋值给data中的变量,就实现了data中数据的更新
fullName: {set: function(newValue) {console.log(newValue)},get: function() {}}
question2:计算属性的缓存(计算属性和methods的对比)
- 如下所示,多次调用计算属性时,只会执行一次对应函数,而多次调用方法时,则会执行多次对应函数
- 相比之下,计算属性要比方法的性能更高的,它的内部是做了缓存的,它会观察这里的firstName和lastName有没有发生变化,如果没有发生变化,则会返回原来的结果,不重新调用。如果发生了变化,就重新执行对应函数。
- 比如之前计算图书总价格的例子,如果我们使用的methods,如果多次使用,就会多次执行该方法,也就会多次执行for循环,这里会影响性能,如果我们使用计算属性,当data中数据没变时,只会执行一次for循环,这样会更好
总结:当我们对数据的一些变化时,就尽量使用计算属性
<div id="app"><h2>{{firstName}} {{lastName}}</h2><h2>{{fullName}}</h2><h2>{{fullName}}</h2><h2>{{fullName}}</h2><h2>{{fullName}}</h2> <!--这里只会打印一次computed--><h2>{{getFullName()}}</h2><h2>{{getFullName()}}</h2><h2>{{getFullName()}}</h2><h2>{{getFullName()}}</h2> <!--这里会打印四次methods--></div><script>const app = new Vue({el: '#app',data: {message: 'hello',firstName: 'ryan',lastName: 'zhang'},computed: {fullName: function () {console.log('computed')return this.firstName + ' ' + this.lastName}},methods: {getFullName: function () {console.log('methods')return this.firstName + ' ' + this.lastName}}})</script>
