Vue 2 | Part 6 计算属性

公孙胜
• 阅读 4804

在这之前,我们往html里面绑定的数据,都是非常直接的。给定一个值,就直接绑定它了。

但是更多的情况下,我们在绑定之前,需要对这些数据做一些处理。这就是计算属性发挥作用的地方了。

有了前面各期知识的加成,这次我们来一个好玩的。我们做一个愿望清单,列表里面是想买的PS4游戏:

Vue 2 | Part 6 计算属性

点击购买某个游戏之后,它会自动从愿望清单移除,出现在已入游戏列表里面。同时,余额也相应减少:

Vue 2 | Part 6 计算属性

当然,这里不涉及任何的真实货币结算,只是点击一下按钮,做出余额相应减少和两边列表更新的效果。

注:游戏价格是PSN上面2016圣诞元旦这段期间的价格,查的当时是港元,所以我们整个demo就使用港元作为货币单位了。

为了避免篇幅过长,这一期的代码只截取重点部分,完整的代码请看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字段表示该游戏是否已购入,初始时所有为false

HTML拆解

  • 使用大胡子语法绑定余额myBalance

在这个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,用鼠标选中了文字的):

Vue 2 | Part 6 计算属性

点击购买游戏(图中可以看到神秘海域已经点击购买了,所以不在愿望清单中),console中没有出现新log,说明computed里面的showCash方法没有再次执行:

Vue 2 | Part 6 计算属性

也就是说,如果showCash方法认为它所依赖的数据this.myCash没有发生变化,它就不会再执行,而是直接返回之前已经计算好的值。

只有在它依赖的数据修改的情况下,才会进行更新:

Vue 2 | Part 6 计算属性

然后我们修改一下html里面的调用方式,在methods里面增加同样的方法:

记得要先屏蔽掉computed里面的同名方法,否则会报错。

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

进入页面的时候执行了一次:

Vue 2 | Part 6 计算属性

点击购买游戏,log增加:

Vue 2 | Part 6 计算属性

可见,即使数据源没有改变,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...

视频攻略:小的不才,为求一赞,自制 本期视频攻略 在此。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Peter20 Peter20
4年前
mysql中like用法
like的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\.name以"李"开头wherenamelike'李%'2\.name中包含"云",“云”可以在任何位置wherenamelike'%云%'3\.第二个和第三个字符是0的值wheresalarylike'\00%'4\
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Easter79 Easter79
3年前
SwiftUI 跨组件数据传递
作者:Cyandev,iOS和MacOS开发者,目前就职于字节跳动0x00前言众所周知,SwiftUI的开发模式与React、Flutter非常相似,即都是声明式UI,由数据驱动(产生)视图,视图也会与数据自动保持同步,框架层会帮你处理“绑定”的问题。在声明式UI中不存在命令式地让一个视图变成xxx
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这