选中
图片
单价
个数
小计
操作
{{ item.price }}
{{ item.num }}
{{ item.num*item.price }}
总价 : ¥
{{ totalPrice }}
🛒空空如也
案例-水果购物车#
需求说明:
- 渲染功能
- 删除功能
- 修改个数
- 全选反选
- 统计选中的总价和总数量
- 持久化到本地
业务技术点总结:
-
渲染:
v-if/v-else
v-for
:class
-
删除:
点击传参
filter
过滤覆盖原数组 -
修改个数:
点击传参
find
(未使用)找对象 -
全选反选:计算属性
computed
完整写法get/set
-
统计总价/总数:计算属性
computed
reduce
条件求和 -
持久化到本地:
watch
监视,localStroage
JSON.stringify
JSON.parse
渲染v-for#
<div class="tr" v-for="(item, index) in fruitList" :key="item.id" v-bind:class="{active:item.isChecked}">
<div class="td"><input type="checkbox" v-model="item.isChecked" /></div>
<div class="td"><img :src="item.icon" alt="" /></div>
<div class="td">{{ item.price }}</div>
<div class="td">
<div class="my-input-number">
<button class="decrease">-</button>
<span class="my-input__inner">{{ item.num }}</span>
<button class="increase">+</button>
</div>
</div>
<div class="td">{{ item.num*item.price }}</div>
<div class="td"><button>删除</button></div>
</div>
删除#
删除按钮点击传递当前id,根据id筛选出其他项并覆盖原对象列表,数据更新视图更新
<div class="td"><button @click="del(item.id)">删除</button></div>
methods: {
del(id) {
this.fruitList = this.fruitList.filter(item => item.id !== id);
},
},
修改个数#
减号自减一,加号自增一
减到数量为一时禁用减号,加号可根据商品库存设限
<div class="my-input-number">
<button class="decrease" @click="item.num--" :disabled="item.num<=1">-</button>
<span class="my-input__inner">{{ item.num }}</span>
<button class="increase" @click="item.num++">+</button>
</div>
全选反选#
全选框绑定
isCheckAll
计算属性
get返回所有小选框是否都被选中的布尔值,同步给全选框
set将全选框状态同步给所有小选框
<label class="check-all">
<input type="checkbox" v-model="isCheckAll" />
全选
</label>
computed: {
isCheckAll: {
// 需要设置值,所以用完整写法
get() {
// 必须所有小选框都选中,全选框才选中--every
return this.fruitList.every(item => item.isChecked);
},
set(value) {
// 基于拿到的全选框值同步所有小选框
this.fruitList.forEach(item => {
item.isChecked = value;
});
},
},
},
统计总价/总数#
总价/总数部分计算的是:勾选上的商品的价格及数量
需要判断
isChecked
为true才计算
<div class="right-box">
<!-- 所有商品总价 -->
<span class="price-box">
总价 : ¥
<span class="price">{{ totalPrice }}</span>
</span>
<!-- 结算按钮 -->
<button class="pay">结算( {{ totalCount }} )</button>
</div>
computed: {
// ...
// 统计选中的总数
totalCount() {
return this.fruitList.reduce((sum, item) => (item.isChecked ? sum + item.num : sum + 0), 0);
},
// 统计选中的总价num*price
totalPrice() {
return this.fruitList.filter(item => item.isChecked).reduce((sum, item) => (sum += item.num * item.price), 0);
},
},
持久化到本地#
用户操作的数据需要存到后台,但这里没有提供接口,所以存到本地
任何一个数据变化都要重新存储,所以用到
watch
将原本的商品数据换成存入本地的数据,为了避免本地没有数据,用逻辑或
||
的短路原理使表达式在左侧为空时取右边表达式默认数据,原本的数据存在
defaultArr
中
// ...
data: {
// 水果列表
fruitList: JSON.parse(localStorage.getItem('list')) || defaultArr,
},
// ...
watch: {
fruitList: {
deep: true,
handler(newValue) {
// 需要将变化后的数据newValue存入本地,记得转JSON格式
localStorage.setItem('list', JSON.stringify(newValue));
},
},
},