Vue 2 | Part 6 計算屬性

在這以前,咱們往html裏面綁定的數據,都是很是直接的。給定一個值,就直接綁定它了。javascript

可是更多的狀況下,咱們在綁定以前,須要對這些數據作一些處理。這就是計算屬性發揮做用的地方了。html

有了前面各期知識的加成,此次咱們來一個好玩的。咱們作一個願望清單,列表裏面是想買的PS4遊戲:vue

final-0

點擊購買某個遊戲以後,它會自動從願望清單移除,出如今已入遊戲列表裏面。同時,餘額也相應減小:java

final-1

固然,這裏不涉及任何的真實貨幣結算,只是點擊一下按鈕,作出餘額相應減小和兩邊列表更新的效果。git

注:遊戲價格是PSN上面2016聖誕元旦這段期間的價格,查的當時是港元,因此咱們整個demo就使用港元做爲貨幣單位了。github

爲了不篇幅過長,這一期的代碼只截取重點部分,完整的代碼請看github代碼庫的版本。數據庫

本期的簡單database

我把查詢到的數據弄成了一個小DB,放在gamesDB.js文件裏面,主要是用來作列表循環,下面是它的樣子:緩存

// gamesDB.js
var games = [
    {
        "id"       : 0,
        "name"     : "神祕海域123",
        "img"      : "../static/images/uncharted-collection.jpg",
        "price"    : 160.80,
        "purchased": false
    },
    /* 餘下的部分省略 */
]

purchased字段表示該遊戲是否已購入,初始時全部爲falseapp

HTML拆解

  • 使用大鬍子語法綁定餘額myBalanceide

在這個demo裏面會所有使用大鬍子語法。由於會遇到像下面這樣,須要在數據先後加額外文字的狀況。若是一些地方用v-text,一些地方用大鬍子,代碼會很難分辨,因此就統一用大鬍子了。

另外,跟金錢有關的部分都會使用toFixed方法來保留兩位小數。

<div class="page-header">
    <h2 class="myCash">個人餘額:HK$ {{ myBalance.toFixed(2) }}</h2>
</div>
  • v-for循環列表

循環願望清單wishList

<div class="gameItem" v-for="item in wishList">
    <!-- v-bind 綁定圖片屬性 -->
    <img :src="item.img">
    <div class="gameInfo">
        <h2 class="name">{{ item.name }}</h2>
        <p class="price">HK$ {{ item.price.toFixed(2) }}</p>
        <!-- v-on 監聽點擊事件 -->
        <button class="btn btn-danger btn-lg" @click="buyGame(item.id)">當即購買</button>
    </div>
</div>

已入遊戲列表myGames的循環同理,只是會減小一些UI:

<div class="gameItem" v-for="item in myGames">
    <img :src="item.img">
    <div class="gameInfo">
        <h2 class="name">{{ item.name }}</h2>
    </div>
</div>

初始的JS

window.games是爲了方便,我在gamesDB.js裏面直接把db掛了在window對象下。在實際工做用請必定要避免這種作法。引入了gamesDB.js以後,data.games就有了我準備好的數據庫裏面的數據了。

另外初始化本身手上持有現金5000。

<script src="../static/js/vue.js" charset="utf-8"></script>
<!-- 引入gamesDB -->
<script src="../static/js/gamesDB.js" charset="utf-8"></script>
var app = new Vue({
    el: '#app',
    data: {
        games: window.games,
        myCash: 5000
    }
})

處理點擊事件

經過ID找到對應的遊戲,修改purchased字段爲true。ID會在html的綁定中傳入:@click="buyGame(item.id)"

var app = new Vue({
    el: '#app',
    data: {
        games: window.games,
        myCash: 5000
    },
    methods: {
        buyGame: function (id) {
            this.games[id].purchased = true
        }
    }
})

讓購入的遊戲顯示在已入清單中,並從願望清單中移除

直接用filter方法篩選出全部purchased字段爲true的遊戲,結果綁定到已入清單。同理,願望清單中只篩選字段值爲false的遊戲。

var app = new Vue({
    el: '#app',
    data: {
        games: window.games,
        myCash: 5000
    },
    methods: {
        buyGame: function (id) {
            this.games[id].purchased = true
        }
    },
    computed: {
        wishList: function () {
            return this.games.filter(function (game) {
                return !game.purchased
            })
        },
        myGames: function () {
            return this.games.filter(function (game) {
                return game.purchased
            })
        }    
    }
})

在這裏你們確定都有一個疑問,computed裏面的方法和methods裏面的方法,到底有什麼不一樣?它們看上去都是同樣的啊。

區別就在於computed裏面的方法會進行緩存,只要方法依賴的數據源不改變,它們就不會被執行。咱們用一個很簡單的例子快速說明一下:

在個人餘額下面插入一個h2:

<h2>data.myCash: {{ showCash }}</h2>

在計算屬性裏面增長一個showCash方法,直接console裏面log一下就知道它有沒有執行過:

var app = new Vue({
    /* 省略其它代碼 */
    computed: {
        showCash: function () {
            console.log('showCash in computed properties')
            // 注意這裏是myCash,它在此次的例子中是一直不變的
            return this.myCash
        }
    }
})

進入頁面的時候執行了一次(留意一下,不變的數字是爲了說明而新加的h2,用鼠標選中了文字的):

computed-1

點擊購買遊戲(圖中能夠看到神祕海域已經點擊購買了,因此不在願望清單中),console中沒有出現新log,說明computed裏面的showCash方法沒有再次執行:

computed-2

也就是說,若是showCash方法認爲它所依賴的數據this.myCash沒有發生變化,它就不會再執行,而是直接返回以前已經計算好的值。

只有在它依賴的數據修改的狀況下,纔會進行更新:

computed-3

而後咱們修改一下html裏面的調用方式,在methods裏面增長一樣的方法:

記得要先屏蔽掉computed裏面的同名方法,不然會報錯。

<h2>data.myCash: {{ showCash() }}</h2>
var app = new Vue({
    /* 省略其它代碼 */
    methods: {
        showCash: function () {
            console.log('showCash in methods')
            return this.myCash
        }
    }
})

進入頁面的時候執行了一次:

methods-1

點擊購買遊戲,log增長:

methods-2

可見,即便數據源沒有改變,methods裏面的showCash方法依然會執行屢次。

計算當前餘額

最後,使用現金總額減掉已入遊戲的總價,就獲得當前餘額啦。

var app = new Vue({
    // 省略其它代碼
    computed: {
        myBalance: function () {
            var sum = 0
            this.myGames.forEach(function (item, index) {
                sum += item.price
            })
            return this.myCash - sum
        }
    }
})

這期就到這裏,敬請期待下一期:組件。

寫在最後

源碼地址:https://github.com/levblanc/v...

視頻攻略:小的不才,爲求一讚,自制 本期視頻攻略 在此。

相關文章
相關標籤/搜索