3. Vue语法--计算属性

一. 计算属性

1. 什么是计算属性?

一般, 咱们是在模板中, 经过插值语法显示data的内容, 但有时候咱们可能须要在{{}}里添加一些计算, 而后在展现出来数据. 这时咱们能够使用到计算属性html

先来举个例子, 好比: 一个班, 有几个学生参加期末考试, 要计算考试的平均分. 咱们来看看, 一般要怎么作?vue

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">考试成绩
    <ul>
        <li v-for="stu in students">{{stu.name}} -- {{stu.score}}</li>
    </ul>

    <p>平均分: <label>{{getAvg()}}</label></p>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            message:"班级考试平均分",
            students: [ {name:"张三", score:90}, {name:"lisi", score:100}, {name:"wangwu", score:99}, {name:"zhaoliu", score:89}, {name:"liuqi", score:95} ]
        },
        methods: {
            getAvg() { let sum = 0; for (let i = 0; i < this.students.length; i++) { console.log(this.students[i].score); let stu = this.students[i]; sum += stu.score; } console.log("平均分:" + sum/this.students.length);
                 return sum/this.students.length;
 }
        }
    })
</script>
</body>
</html>

咱们定义了一组学生的成绩. 而后将其显示在页面上, 而后经过方法getAvg计算平均分. 缓存

 

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">考试成绩
    <ul>
        <li v-for="stu in students">{{stu.name}} -- {{stu.score}}</li>
    </ul>

    <p>平均分: <label>{{avg}}</label></p>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            message:"班级考试平均分",
            students: [
                {name:"zhangsan", score:90},
                {name:"lisi", score:100},
                {name:"wangwu", score:99},
                {name:"zhaoliu", score:89},
                {name:"liuqi", score:95}
            ]
        },
        computed: { avg: function() { let sum = 0; for (let i = 0; i < this.students.length; i++) { console.log(this.students[i].score); let stu = this.students[i]; sum += stu.score; } console.log("平均分:" + sum/this.students.length); return sum/this.students.length;  } },
        methods: {

        }
    })
</script>
</body>
</html>

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

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

2. 计算属性computed的缓存功能

咱们用案例来讲明他们之间的区别. spa

案例1. methods方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <p> Origin Message: {{message}}</p>
    <p>Mthod Message:{{getMessage()}}</p> <p>Mthod Grade:{{getGrade()}}</p> <p>Mthod Class:{{getClass()}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            message:"班级考试平均分",
            className: "1班",
            gradeName:"一年级"
        },
        methods: { getGrade: function(){ console.log("调用Grade计算") return "方法" + this.gradeName }, getClass: function(){ console.log("调用class计算") return "方法" + this.className }, getMessage: function(){ console.log("调用message计算") return "方法" + this.message } }
    })
</script>
</body>
</html>

 

 

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

 案例2. computed计算属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <p> Origin Message: {{message}}</p>
    <p>Mthod Message:{{getMessage}}</p>
    <p>Mthod Grade:{{getGrade}}</p>
    <p>Mthod Class:{{getClass}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            message:"班级考试平均分",
            className: "1班",
            gradeName:"一年级"
        },
        computed: { getGrade: function(){ console.log("调用Grade计算") return "方法" + this.gradeName }, getClass: function(){ console.log("调用class计算") return "方法" + this.className }, getMessage: function(){ console.log("调用message计算") return "方法" + this.message } }
    })
</script>
</body>
</html>

控制台输出htm

 

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

 

案例3:  再看一个computed缓存的例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <p>调用方法</p>
    <p>{{getMes()}}</p>
    <p>{{getMes()}}</p>
    <p>{{getMes()}}</p>
    <p>{{getMes()}}</p>


    <p>调用计算属性</p>
    <p>{{mes}}</p>
    <p>{{mes}}</p>
    <p>{{mes}}</p>
    <p>{{mes}}</p>

</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            firstName: "Elon",
            lastName: "Musk"
        },
        computed: { mes: function(){ console.log("调用计算属性") return this.firstName + " " + this.lastName } },
        methods: { getMes: function(){ console.log("调用method方法") return this.firstName + " " + this.lastName } }
    })
</script>
</body>
</html>

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

 

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

 

总结

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

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

3. 计算属性的getter和setter访问器

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

仍是这个案例, 咱们来看看代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">{{message}} {{avg}}</div>

<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: "计算平均分:",
            students: [
                {name:"zhangsan", score:90},
                {name:"lisi", score:100},
                {name:"wangwu", score:99},
                {name:"zhaoliu", score:89},
                {name:"liuqi", score:95}
            ]
        },
        computed: {
            avg: function() {
                let sum = 0;
                for (let i = 0; i < this.students.length; i++) {
                    console.log(this.students[i].score);
                    let stu = this.students[i];
                    sum += stu.score;
                }
                console.log("平均分:" + sum/this.students.length);
                return sum/this.students.length;
            }
          
        }
    });
</script>
</body>
</html>

 咱们在计算平均分的时候, 是把avg当作一个属性来对待的, 因此,调用的时候这么写{{avg}}, 而不是{{avg()}}. 可是咱们定义的时候倒是给定义成方法了, 为何会这样呢?

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

 

  • 其实计算属性自己是定义为了一个属性. 例如: 咱们定义test, 一般咱们定义属性是这么定义的
test: "这是一个属性"
  • 在计算属性里, 属性值是一个对象, 因此, 咱们要这么定义
computed: {
    test: { }
}
  • 对象的内部有两个方法, 一个是get方法, 一个是set方法. 这时在get方法中return一个abc, 这是, 在页面显示的就应该是abc
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">{{message}} --- {{avg}} --- {{test}}</div>

<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: "计算平均分:",
            students: [
                {name:"zhangsan", score:90},
                {name:"lisi", score:100},
                {name:"wangwu", score:99},
                {name:"zhaoliu", score:89},
                {name:"liuqi", score:95}
            ]
        },
        computed: {
            avg: function() {
                let sum = 0;
                for (let i = 0; i < this.students.length; i++) {
                    console.log(this.students[i].score);
                    let stu = this.students[i];
                    sum += stu.score;
                }
                console.log("平均分:" + sum/this.students.length);
                return sum/this.students.length;
            },
            test : { set: function(newValue) { this.message = newValue; console.log("调用setter") }, get: function() { return "abc"  } }
        }
    });
</script>
</body>
</html>

看看效果

确实打印输出了abc

 

 

  • 由于有get方法和set方法, 因此, 咱们能够修改test的值,  以下: 修改了app.test的值, 最终改变了message的值.

 

 

  • 然而, 计算属性一般只实现get方法, 而不实现set方法. 咱们是计算后输出, 而不容许北外不修改,  这时计算属性就只剩下一个get方法, 最后咱们将其简写, 去掉get, 就是咱们一般看到的写法
computed: {
    avg: function() {
        let sum = 0;
        for (let i = 0; i < this.students.length; i++) {
            console.log(this.students[i].score);
            let stu = this.students[i];
            sum += stu.score;
        }
        console.log("平均分:" + sum/this.students.length);
        return sum/this.students.length;
    },
    avg1 : function() { return "abc" }
}

虽然写法和method差很少. 但本质上, 计算属性仍是属性, 因此, 和属性的写法是同样的.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

as

相关文章
相关标签/搜索