filter

现在我们完成一个需求,将显示区域划分为上下两个部分,一个是零食的未购区域,一个是零食的已购区域。

首先我们需要将已购买和未购买筛选出来,这时候我们就用到了数组的filter方法,我们在v-for对foods添加filter方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<section>
<h2>已购零食</h2>
<ul>
<li v-for="food in foods.filter(item => item.purchased)">
<img v-bind:src="food.image">
<span>{{ food.name }}</span>
<input type="checkbox" v-model="food.purchased">
</li>
</ul>
</section>

<section>
<h2>未购零食</h2>
<ul>
<li v-for="food in foods.filter(item => !item.purchased)">
<img v-bind:src="food.image">
<span>{{ food.name }}</span>
<input type="checkbox" v-model="food.purchased">
</li>
</ul>
</section>

这时候,我们会发现我们页面出现了一些问题,它并不能好好的工作。

image.png

key

上面这个问题是因为,vue在进行遍历数组的时候,实际上是遍历得到item,index,而Vue默认会将key绑定到index,而key是Vue用来跟踪和更新元素的。

也就是说我们页面上显示的元素,是index所对的结果。因此对于数组来说,上下两个清单就会出现相同的key。因此我们需要显式的改写key绑定的值。

一般而言,我们会选择一个不相同的值(主键)作为这个key,因此我们这里选择id这个值作为key

1
2
3
<li v-for="food in foods.filter(item => item.purchased)" v-bind:key="food.id">

<li v-for="food in foods.filter(item => !item.purchased)" v-bind:key="food.id">

由于v-bind经常需要用到,因此Vue提供了一个缩写给我吗使用—— :,直接用:就可以替代v-bind:

修改完成后,我们重新回到页面,会发现我们的问题修复了。

v-show

v-show可以使得元素展示或者不展示在页面上。它有两个取值,如果为true,则会显示元素,如果为false,则不显示。

我们利用这个属性可以完成需求,我们想要当已购零食或者未购零食为空时,则隐藏标题。由于我们filter返回的是数组,因此我们可以用数组长度来判断是否显示,我们可以将代码这么改

1
2
3
<section v-show="foods.filter(item => item.purchased).length">

<section v-show="foods.filter(item => !item.purchased).length">

image.png

computed

由于感觉过滤这部分内容重复过高,因此我们可以通过computed来将这部分代码单独列出来,作为一个函数。

computed是一个在createApp内的一个对象,因此我们是需要在data()外编写的。

1
2
3
4
5
6
7
8
computed: {
beforeBuy() {
return this.foods.filter(item => !item.purchased);
},
afterBuy() {
return this.foods.filter(item => item.purchased);
}
}