在这以前,咱们往html里面绑定的数据,都是很是直接的。给定一个值,就直接绑定它了。javascript
可是更多的状况下,咱们在绑定以前,须要对这些数据作一些处理。这就是计算属性发挥做用的地方了。html
有了前面各期知识的加成,此次咱们来一个好玩的。咱们作一个愿望清单,列表里面是想买的PS4游戏:vue
点击购买某个游戏以后,它会自动从愿望清单移除,出如今已入游戏列表里面。同时,余额也相应减小:java
固然,这里不涉及任何的真实货币结算,只是点击一下按钮,作出余额相应减小和两边列表更新的效果。git
注:游戏价格是PSN上面2016圣诞元旦这段期间的价格,查的当时是港元,因此咱们整个demo就使用港元做为货币单位了。github
为了不篇幅过长,这一期的代码只截取重点部分,完整的代码请看github代码库的版本。数据库
我把查询到的数据弄成了一个小DB,放在gamesDB.js
文件里面,主要是用来作列表循环,下面是它的样子:缓存
// gamesDB.js var games = [ { "id" : 0, "name" : "神秘海域123", "img" : "../static/images/uncharted-collection.jpg", "price" : 160.80, "purchased": false }, /* 余下的部分省略 */ ]
purchased
字段表示该游戏是否已购入,初始时全部为false
。app
使用大胡子语法绑定余额myBalance
ide
在这个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>
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
,用鼠标选中了文字的):
点击购买游戏(图中能够看到神秘海域已经点击购买了,因此不在愿望清单中),console中没有出现新log,说明computed
里面的showCash
方法没有再次执行:
也就是说,若是showCash
方法认为它所依赖的数据this.myCash
没有发生变化,它就不会再执行,而是直接返回以前已经计算好的值。
只有在它依赖的数据修改的状况下,才会进行更新:
而后咱们修改一下html里面的调用方式,在methods
里面增长一样的方法:
记得要先屏蔽掉computed
里面的同名方法,不然会报错。
<h2>data.myCash: {{ showCash() }}</h2>
var app = new Vue({ /* 省略其它代码 */ methods: { showCash: function () { console.log('showCash in methods') return this.myCash } } })
进入页面的时候执行了一次:
点击购买游戏,log增长:
可见,即便数据源没有改变,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...
视频攻略:小的不才,为求一赞,自制 本期视频攻略 在此。