通常, 我们是在模板中, 通过插值语法显示data的内容, 但有时候我们可能需要在{{}}里添加一些计算, 然后在展示出来数据. 这时我们可以使用到计算属性

先来举个例子, 比如: 一个班, 有几个学生参加期末考试, 要计算考试的平均分. 我们来看看, 通常要怎么做?

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">考试成绩
  9. <ul>
  10. <li v-for="stu in students">{{stu.name}} -- {{stu.score}}</li>
  11. </ul>
  12. <p>平均分: <label>{{getAvg()}}</label></p>
  13. </div>
  14. <script src="../js/vue.js"></script>
  15. <script>
  16. const app = new Vue({
  17. el: "#app",
  18. data: {
  19. message:"班级考试平均分",
  20. students: [
  21. {name:"张三", score:90},
  22. {name:"lisi", score:100},
  23. {name:"wangwu", score:99},
  24. {name:"zhaoliu", score:89},
  25. {name:"liuqi", score:95}
  26. ]
  27. },
  28. methods: {
  29. getAvg() {
  30. let sum = 0;
  31. for (let i = 0; i < this.students.length; i++) {
  32. console.log(this.students[i].score);
  33. let stu = this.students[i];
  34. sum += stu.score;
  35. }
  36. console.log("平均分:" + sum/this.students.length);
  37. return sum/this.students.length;
  38. }
  39. }
  40. })
  41. </script>
  42. </body>
  43. </html>

我们定义了一组学生的成绩. 然后将其显示在页面上, 然后通过方法getAvg计算平均分. 

 

 这里我们在获取平均分的时候, 使用的是{{getAve()}} 其实, 平均分我们理解更像是一个属性, 而不是一个方法. 为了方便计算, vue给我们提供了一个computed属性, 专门用来做计算. computed中定义的也是方法, 这个方法的方法名通常都定义为名词. 我们来看一下使用

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">考试成绩
  9. <ul>
  10. <li v-for="stu in students">{{stu.name}} -- {{stu.score}}</li>
  11. </ul>
  12.  
  13. <p>平均分: <label>{{avg}}</label></p>
  14. </div>
  15. <script src="../js/vue.js"></script>
  16. <script>
  17. const app = new Vue({
  18. el: "#app",
  19. data: {
  20. message:"班级考试平均分",
  21. students: [
  22. {name:"zhangsan", score:90},
  23. {name:"lisi", score:100},
  24. {name:"wangwu", score:99},
  25. {name:"zhaoliu", score:89},
  26. {name:"liuqi", score:95}
  27. ]
  28. },
  29. computed: {
  30. avg: function() {
  31. let sum = 0;
  32. for (let i = 0; i < this.students.length; i++) {
  33. console.log(this.students[i].score);
  34. let stu = this.students[i];
  35. sum += stu.score;
  36. }
  37. console.log("平均分:" + sum/this.students.length);
  38. return sum/this.students.length;
  39. }
  40. },
  41. methods: {
  42. }
  43. })
  44. </script>
  45. </body>
  46. </html>

这里,增加了一个computed属性, 里面定义了avg方法, 没错, 本质还是方法, 但命名的时候, 将其命名为名词.

眼尖的同学应该已经发现了, 这好像和methods方法一样啊, 就是换了个名字. 那computed计算属性和methods方法有什么区别呢?

我们用案例来说明他们之间的区别. 

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <p> Origin Message: {{message}}</p>
  10. <p>Mthod Message:{{getMessage()}}</p>
  11. <p>Mthod Grade:{{getGrade()}}</p>
  12. <p>Mthod Class:{{getClass()}}</p>
  13. </div>
  14. <script src="../js/vue.js"></script>
  15. <script>
  16. const app = new Vue({
  17. el: "#app",
  18. data: {
  19. message:"班级考试平均分",
  20. className: "1班",
  21. gradeName:"一年级"
  22. },
  23. methods: {
  24. getGrade: function(){
  25. console.log("调用Grade计算")
  26. return "方法" + this.gradeName
  27. },
  28. getClass: function(){
  29. console.log("调用class计算")
  30. return "方法" + this.className
  31. },
  32. getMessage: function(){
  33. console.log("调用message计算")
  34. return "方法" + this.message
  35. }
  36. }
  37. })
  38. </script>
  39. </body>
  40. </html>

 

 

 我们发现, 在修改一个属性, 其他属性都没变化的情况下, 我们发现methods里的方法都被执行了一遍

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <p> Origin Message: {{message}}</p>
  10. <p>Mthod Message:{{getMessage}}</p>
  11. <p>Mthod Grade:{{getGrade}}</p>
  12. <p>Mthod Class:{{getClass}}</p>
  13. </div>
  14. <script src="../js/vue.js"></script>
  15. <script>
  16. const app = new Vue({
  17. el: "#app",
  18. data: {
  19. message:"班级考试平均分",
  20. className: "1班",
  21. gradeName:"一年级"
  22. },
  23. computed: {
  24. getGrade: function(){
  25. console.log("调用Grade计算")
  26. return "方法" + this.gradeName
  27. },
  28. getClass: function(){
  29. console.log("调用class计算")
  30. return "方法" + this.className
  31. },
  32. getMessage: function(){
  33. console.log("调用message计算")
  34. return "方法" + this.message
  35. }
  36. }
  37. })
  38. </script>
  39. </body>
  40. </html>

控制台输出

 

 我们发现, 当控制台修改其中一个属性值, 只有调用这个属性的方法会重新执行

 

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <p>调用方法</p>
  10. <p>{{getMes()}}</p>
  11. <p>{{getMes()}}</p>
  12. <p>{{getMes()}}</p>
  13. <p>{{getMes()}}</p>
  14. <p>调用计算属性</p>
  15. <p>{{mes}}</p>
  16. <p>{{mes}}</p>
  17. <p>{{mes}}</p>
  18. <p>{{mes}}</p>
  19. </div>
  20. <script src="../js/vue.js"></script>
  21. <script>
  22. const app = new Vue({
  23. el: "#app",
  24. data: {
  25. firstName: "Elon",
  26. lastName: "Musk"
  27. },
  28. computed: {
  29. mes: function(){
  30. console.log("调用计算属性")
  31. return this.firstName + " " + this.lastName
  32. }
  33. },
  34. methods: {
  35. getMes: function(){
  36. console.log("调用method方法")
  37. return this.firstName + " " + this.lastName
  38. }
  39. }
  40. })
  41. </script>
  42. </body>
  43. </html>

这是两种方式的调用, 但是结果都一样, 都是打印输出姓名, 计算属性mes调用了四次, 方法getMes()也调用了四次, 我们来看看运行结果

 

 两次打印的结果是一样的, 但是调用getMes()调用了4次, 而mes计算属性只计算了一次.

 

  • methods方法和computed计算属性,两种方式的最终结果确实是完全相同
  • 不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值,多次访问getMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
  • methods方法,每当触发重新渲染时,调用方法将总会再次执行函数。

所以,官网说,对于任何复杂逻辑,都应当使用计算属性。

问题: 我们发现, 在计算属性和methods方法调用的是偶还有一点不同, 那就是调用方式不同. method方调用是{{getMessage()}}, 而计算属性是{{getMessage}}, 我们上面不是说计算属性中定义的也是方法么? 为什么不需要使用()呢? 下面来研究一下

还是这个案例, 我们来看看代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">{{message}} {{avg}}</div>
  9.  
  10. <script src="../js/vue.js"></script>
  11. <script>
  12. var app = new Vue({
  13. el: "#app",
  14. data: {
  15. message: "计算平均分:",
  16. students: [
  17. {name:"zhangsan", score:90},
  18. {name:"lisi", score:100},
  19. {name:"wangwu", score:99},
  20. {name:"zhaoliu", score:89},
  21. {name:"liuqi", score:95}
  22. ]
  23. },
  24. computed: {
  25. avg: function() {
  26. let sum = 0;
  27. for (let i = 0; i < this.students.length; i++) {
  28. console.log(this.students[i].score);
  29. let stu = this.students[i];
  30. sum += stu.score;
  31. }
  32. console.log("平均分:" + sum/this.students.length);
  33. return sum/this.students.length;
  34. }
  35. }
  36. });
  37. </script>
  38. </body>
  39. </html>

 我们在计算平均分的时候, 是把avg当做一个属性来对待的, 所以,调用的时候这么写{{avg}}, 而不是{{avg()}}. 但是我们定义的时候却是给定义成方法了, 为什么会这样呢?

下面我们来研究computed完整的写法, 研究完这个, 就知道为什么这么写了. 

 

  • 其实计算属性本身是定义为了一个属性. 例如: 我们定义test, 通常我们定义属性是这么定义的
  1. test: "这是一个属性"
  • 在计算属性里, 属性值是一个对象, 所以, 我们要这么定义
  1. computed: {
  2. test: {
  3. }
  4. }
  • 对象的内部有两个方法, 一个是get方法, 一个是set方法. 这时在get方法中return一个abc, 这是, 在页面显示的就应该是abc
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">{{message}} --- {{avg}} --- {{test}}</div>
  9.  
  10. <script src="../js/vue.js"></script>
  11. <script>
  12. var app = new Vue({
  13. el: "#app",
  14. data: {
  15. message: "计算平均分:",
  16. students: [
  17. {name:"zhangsan", score:90},
  18. {name:"lisi", score:100},
  19. {name:"wangwu", score:99},
  20. {name:"zhaoliu", score:89},
  21. {name:"liuqi", score:95}
  22. ]
  23. },
  24. computed: {
  25. avg: function() {
  26. let sum = 0;
  27. for (let i = 0; i < this.students.length; i++) {
  28. console.log(this.students[i].score);
  29. let stu = this.students[i];
  30. sum += stu.score;
  31. }
  32. console.log("平均分:" + sum/this.students.length);
  33. return sum/this.students.length;
  34. },
  35. test : {
  36. set: function(newValue) {
  37. this.message = newValue;
  38. console.log("调用setter")
  39. },
  40. get: function() {
  41. return "abc"
  42. }
  43. }
  44. }
  45. });
  46. </script>
  47. </body>
  48. </html>

看看效果

确实打印输出了abc

 

 

  • 因为有get方法和set方法, 所以, 我们可以修改test的值,  如下: 修改了app.test的值, 最终改变了message的值.

 

 

  • 然而, 计算属性通常只实现get方法, 而不实现set方法. 我们是计算后输出, 而不允许北外不修改,  这时计算属性就只剩下一个get方法, 最后我们将其简写, 去掉get, 就是我们通常看到的写法
  1. computed: {
  2. avg: function() {
  3. let sum = 0;
  4. for (let i = 0; i < this.students.length; i++) {
  5. console.log(this.students[i].score);
  6. let stu = this.students[i];
  7. sum += stu.score;
  8. }
  9. console.log("平均分:" + sum/this.students.length);
  10. return sum/this.students.length;
  11. },
  12. avg1 : function() {
  13. return "abc"
  14. }
  15. }

虽然写法和method差不多. 但本质上, 计算属性还是属性, 所以, 和属性的写法是一样的.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

as

 

版权声明:本文为ITPower原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/ITPower/p/14418949.html