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

相關文章
相關標籤/搜索