效果图
友情提示,vue ui创建项目可以选择vue3版本
先介绍下本文用到的Vue3新语法
- 响应式数据:reactive引用类型, ref基本类型
- 代码基本都写在setup函数里,写完的响应式数据和方法要return
- computed变成函数式并接收一个回调函数
正文
一. 模拟数据
// goodsData的数据结构
const goodsData = [{
img: 'https://tse1-mm.cn.bing.net/th/id/OIP.jMZGCh1dDdJH-KwzQs8vYgHaKG?w=206&h=280&c=7&o=5&dpr=1.25&pid=1.7',
select: false, 是否被选中
title: '白大褂',
price: 38,
desc: '女士 短袖',
count: 1,
id: 1
}]
const goodsDatas = reactive(goodsData);
// 渲染的话都是v-for vue3没有变动
二. 按页面结构分为三部分,头部、内容和底部
- 头部DOM结构
<header>
<h2>购物车 <span @click="isManage = !isManage">{{isManage ? '完成' : '管理'}}</span></h2>
<p>共{{goodsDatas.length}}件宝贝</p>
</header>
// js
const isManage = ref(false)
- isManage表示购物车状态(结算或管理)并显示不同的文字
- 统计宝贝个数goodsDatas.length很方便
三. 内容
- DOM结构: 遍历goodsDatas 。单选图片判断select属性用v-show切换,引入图片用require 最后要记得return
<ul id="goods">
<li v-for="(item, index) of goodsDatas" :key="item.id">
<img :src="unselect" alt="" v-show="!item.select" class="select" @click="selectItem(index)">
<img :src="selected" alt="" v-show="item.select" class="select" @click="selectItem(index)">
<img :src="item.img" alt="" class="poster">
<aside>
<h6>{{item.title}}</h6>
<p>{{item.desc}}</p>
<h5>¥<b>{{item.price}}</b>
<div class="change-count">
<button class="l" @click="minus(index)">-</button>
<input type="text" v-model="item.count" @input="inputCount(item.count, index)">
<button class="r" @click="add(index)">+</button>
</div>
</h5>
</aside>
</li>
</ul>
- 单选宝贝selectItem(index)。select = !select展示不同的图片。every判断所有宝贝的select状态是否全部选中,如果全部选中isSelectAll为true反之为false
function selectItem(index: number): void {
const itemSelect: boolean = goodsDatas[index].select
goodsDatas[index].select = !itemSelect
const all:boolean = goodsDatas.every(item => {
return item.select === true
})
isSelectAll.value = all ? true : false
}
- 更改数量item.count. 这里用三个方法minus、add和inputCount,分别是减少、添加和用户输入。
function inputCount(count: number|string, index: number): void {
if(!count || count == 'Na') {
goodsDatas[index].count = 1
return;
}
goodsDatas[index].count = parseInt(String(count))
}
function minus(index: number): void {
const currCount = goodsDatas[index].count
if(currCount <= 1) return;
goodsDatas[index].count -= 1
}
function add(index: number): void {
goodsDatas[index].count += 1
}
四. 底部
- DOM结构,unselect和selected代表不同状态的图片,合计total用computed计算
<footer>
<img :src="unselect" alt="" v-show="!isSelectAll" @click="selectAll">
<img :src="selected" alt="" v-show="isSelectAll" @click="selectAll">
<span>全选</span>
<h6><em>合计:</em><i>¥{{total}}</i></h6>
<button @click="finish">{{isManage ? '移除' : '结算'}}</button>
</footer>
- selectAll 如果全选则遍历goodsData更改item.select为true,反之为false
function selectAll(): void {
isSelectAll.value = !isSelectAll.value
if(isSelectAll.value) {
goodsDatas.forEach(item => {
item.select = true
})
} else {
goodsDatas.forEach(item => {
item.select = false
})
}
}
- 最关键的total. 如果购物车是管理状态直接返回 0,否则map遍历goodsData相加价格currentPrice是单个宝贝的总价
const total = computed(() => {
if(isManage.value) return 0;
let n: number = 0
goodsDatas.map(item => {
if(item.select) {
const currentPrice = item.price * item.count
n = n + currentPrice
}
})
return n
})
至此 我们购物车到此完成了
本文代码地址:git地址
🏆 掘金技术征文|双节特别篇