什么是计算属性?

  • 我们在模版template中,我们可以使用 {{ }} 这种模版语法来显示一些 data 中的数据的
  • 但是在某些情况下,我们是需要对一些数据进行一些转化后再进行显示,或者将多个数据合并在一起再进行展示,如下:

    1. <div id="app">
    2. <h2>{{firstName + ' ' + lastName}}</h2>
    3. <h2>{{firstName}} {{lastName}}</h2>
    4. <!-- 如上两种写法都可以实现想要的效果,但是很不好用,很长 -->
    5. <!-- 我想要用更简单的方法 -->
    6. <!-- 1.使用方法来进行字符串的拼接 -->
    7. <h2>{{getFullName()}}</h2>
    8. <!-- 2.使用计算属性 -->
    9. <h2>{{fullName}}</h2>
    10. </div>
    11. <script>
    12. const app = new Vue({
    13. el: '#app',
    14. data: {
    15. message: 'hello',
    16. firstName: 'Ryan',
    17. lastName: 'Zhang'
    18. },
    19. computed: {
    20. fullName: function() {
    21. return this.firstName + ' ' + this.lastName;
    22. }
    23. },
    24. methods: {
    25. getFullName: function() {
    26. return this.firstName + ' ' + this.lastName;
    27. }
    28. }
    29. })
    30. </script>
  • 其实我们也是可以使用methods来进行拼接的,定义一个getFullName方法,在模版字符串中进行方法的调用即可,但是有个问题,这里使用 getFullName() 来进行调用不太合适,因为我们这里想用的是一个变量而不是一个方法,所以就引出了计算属性来解决这个问题

  • 计算属性:当我们想要对我们的数据进行某种变化之后再进行显示的话,可以在计算属性中重新定义一个属性,并且返回变化之后的数据
    • computed中定义其实也是一个个方法,但是起的名字并不像methods里面的方法一样都是动词开头的(如 getFullName 这种的),computed中的方法起的名字都是一些名词(如 fullName)
    • 而且 computed 翻译为 计算属性 ,所以我们尽量按照属性的方式来起名字
    • 注意:这里调用计算属性中定义的方法时,是不需要加()的!
    • 本质:其实这里的就是一个属性,但是Vue中只实现了它的 get() 方法

计算属性的复杂操作

  • 显示四本书的总价格

    1. <div id="app">
    2. <h2>总价格:{{totalPrice}}</h2>
    3. </div>
    4. <script>
    5. const app = new Vue({
    6. el: '#app',
    7. data: {
    8. books: [
    9. {id:110, name: 'Unix编程艺术', price:119},
    10. {id:111, name: '代码大全', price:120},
    11. {id:112, name: '深入理解计算机原理', price:121},
    12. {id:113, name: '现代操作系统', price:122},
    13. ]
    14. },
    15. computed: {
    16. totalPrice: function() {
    17. let result = 0
    18. for(let i=0; i<this.books.length; i++) {
    19. result += this.books[i] .price
    20. }
    21. for(let i in this.books) {~~~}
    22. for(let book of this.books) {~~~}
    23. }
    24. }
    25. })
    26. </script>
  • 计算属性和methods有很大的区别:计算属性在多次调用时只会调用一次,而methods调用几次就会执行几次,是没有缓存的,性能更低地点

计算属性的getter和setter

question1:为什么使用计算属性时,不用加上括号来调用,而是直接使用名称即可?

  • 计算属性computed,它是一个对象{ },里面的内容其实就是一个个键值对,比如这里的fullName就是属性名,后面的对象就是属性值
  • 只不过这个对象中放的是两个函数,一个是set函数,一个是get函数,分别对应不同的功能
  • 我们使用fullName这个属性时,其实就是去调用其内部的 get() 方法
  • 计算属性这个东西,一般只需要实现它的 get() 方法就可以了,不用实现 set() 方法,只实现 get() 方法其实就是实现了fullName的只读属性
  • 一般我们在使用时,每次都是只写 get() 方法,所以为了简便,Vue就帮我们封装成了这种写法:fullName: function() { ~ }
  • 所以这也就回答了,为什么不用小括号来调用计算属性,fullName不是一个函数,而是一个属性,我们只是使用这个属性名,它其实是内部调用的 get() 方法的!!

    1. const app = new Vue({
    2. el: '#app',
    3. data: {
    4. firstName: 'ryan',
    5. lastName: 'zhang'
    6. },
    7. computed: {
    8. fullName: {
    9. set: function() {
    10. },
    11. get: function() {
    12. return this.firstName + ' ' + this.lastName
    13. }
    14. }
    15. }
    16. })
  • 如果我们想要实现 set() 方法,当data中的值发生变化时(比如直接修改 app.fullName = ‘Kobe Bryant’),这时就会调用 set() 方法,而且一般要给 set() 方法传递一个参数newValue,如下

  • 这时就会打印我们修改后的新值,而且我们最好将这个新值进行处理后,再赋值给data中的变量,就实现了data中数据的更新

    1. fullName: {
    2. set: function(newValue) {
    3. console.log(newValue)
    4. },
    5. get: function() {
    6. }
    7. }

question2:计算属性的缓存(计算属性和methods的对比)

  • 如下所示,多次调用计算属性时,只会执行一次对应函数,而多次调用方法时,则会执行多次对应函数
  • 相比之下,计算属性要比方法的性能更高的,它的内部是做了缓存的,它会观察这里的firstName和lastName有没有发生变化,如果没有发生变化,则会返回原来的结果,不重新调用。如果发生了变化,就重新执行对应函数。
  • 比如之前计算图书总价格的例子,如果我们使用的methods,如果多次使用,就会多次执行该方法,也就会多次执行for循环,这里会影响性能,如果我们使用计算属性,当data中数据没变时,只会执行一次for循环,这样会更好
  • 总结:当我们对数据的一些变化时,就尽量使用计算属性

    1. <div id="app">
    2. <h2>{{firstName}} {{lastName}}</h2>
    3. <h2>{{fullName}}</h2>
    4. <h2>{{fullName}}</h2>
    5. <h2>{{fullName}}</h2>
    6. <h2>{{fullName}}</h2> <!--这里只会打印一次computed-->
    7. <h2>{{getFullName()}}</h2>
    8. <h2>{{getFullName()}}</h2>
    9. <h2>{{getFullName()}}</h2>
    10. <h2>{{getFullName()}}</h2> <!--这里会打印四次methods-->
    11. </div>
    12. <script>
    13. const app = new Vue({
    14. el: '#app',
    15. data: {
    16. message: 'hello',
    17. firstName: 'ryan',
    18. lastName: 'zhang'
    19. },
    20. computed: {
    21. fullName: function () {
    22. console.log('computed')
    23. return this.firstName + ' ' + this.lastName
    24. }
    25. },
    26. methods: {
    27. getFullName: function () {
    28. console.log('methods')
    29. return this.firstName + ' ' + this.lastName
    30. }
    31. }
    32. })
    33. </script>