需求:
- 渲染功能
- 删除功能 filter过率
- 修改个数
- 全选反选
- 统计选中的总价和总数量 计算属性
- 持久化到本地
思路
渲染功能
修改了三步
<style>
* {
margin: 0;
padding: 0;
}
.banner-box {
margin-top: 30px;
margin-left: 400px;
}
.tr {
margin-left: 400px;
width: 500px;
font-size: 20px;
border-left: 15px;
}
.box1 {
padding-right: 10px;
}
.td {
float: left;
width: 72px;
height: 45px;
}
.tractive {
background-color: antiquewhite;
}
</style>
<div class="app-container" id="app">
<!-- 顶部banner -->
<div class="banner-box"><img
src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F7252d6a8-c798-4582-a586-45d3a1b60855%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1708512060&t=8e627cb6e82387038e4a794c5dea2686"
width="500px" height="300px"></div>
<!-- 购物车主体 -->
<div class="main" v-if="fruitList.length>0">
//此处为第一步,主体与空空如也的选择
<div class="table">
<!-- 头部 -->
<div class="tr">
<th>
<td class="box1">选中</td>
<td class="box1">图片</td>
<td class="box1">单价</td>
<td class="box1">个数</td>
<td class="box1">小计</td>
<td class="box1">制作</td>
</th>
</div>
</div>
<!-- 身体 -->
<div class="tbody">
<div v-for="(item,index) in fruitList" :key="item.id" class="tr" :class="{active:item.isChecked}">
//此处为第二步背景颜色和选中的统一
//v-for进行渲染将列表中的元素呈现
<div class="td"><input type="checkbox" v-model="item.isChecked"></div>
<div class="td"><img :src="item.icon" width="30px" height="30px"></div>
<div class="td">{{item.price}}</div>
<div class="td">
<div class="my-input-number">
<button class="decrease" @click="item.num--">-</button>
<span class="my-input__inner">{{item.num}}</span>
<button class="increase" @click="item.num++">+</button>
</div>
</div>
<div class="td">{{item.num*item.price}}</div>
<div class="td"><button>删除</button></div>
</div>
</div>
</div>
<!-- 底部 -->
<div class="bottom">
</div>
</div>
<div class="empty" v-else> 空空如也</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
//水果列表
fruitList: [
{
id: 1,
icon: './img/草莓.png',
isChecked: true,
num: 2,
price: 6,
},
{
id: 2,
icon: './img/香蕉.png',
isChecked: false,
num: 7,
price: 20,
},
{
id: 3,
icon: './img/樱桃.png',
isChecked: true,
num: 2,
price: 6,
}
]
}
})
</script>
删除
<style>
* {
margin: 0;
padding: 0;
}
.banner-box {
margin-top: 30px;
margin-left: 400px;
}
.tr {
margin-left: 400px;
width: 500px;
font-size: 20px;
border-left: 15px;
}
.box1 {
padding-right: 10px;
}
.td {
float: left;
width: 72px;
height: 45px;
}
.tractive {
background-color: antiquewhite;
}
</style>
<div class="app-container" id="app">
<!-- 顶部banner -->
<div class="banner-box"><img
src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F7252d6a8-c798-4582-a586-45d3a1b60855%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1708512060&t=8e627cb6e82387038e4a794c5dea2686"
width="500px" height="300px"></div>
<!-- 购物车主体 -->
<div class="main" v-if="fruitList.length>0">
<div class="table">
<!-- 头部 -->
<div class="tr">
<th>
<td class="box1">选中</td>
<td class="box1">图片</td>
<td class="box1">单价</td>
<td class="box1">个数</td>
<td class="box1">小计</td>
<td class="box1">制作</td>
</th>
</div>
</div>
<!-- 身体 -->
<div class="tbody">
<div v-for="(item,index) in fruitList" :key="item.id" class="tr" :class="{active:item.isChecked}">
<div class="td"><input type="checkbox" v-model="item.isChecked"></div>
<div class="td"><img :src="item.icon" width="30px" height="30px"></div>
<div class="td">{{item.price}}</div>
<div class="td">
<div class="my-input-number">
<button :disabled="item.num==1" class="decrease" @click="item.num--">-</button>
<span class="my-input__inner">{{item.num}}</span>
<button class="increase" @click="item.num++">+</button>
//添加点击时数字加减,并且当减到1时,减禁用
</div>
</div>
<div class="td">{{item.num*item.price}}</div>
<div class="td"><button @click="del(item.id)">删除</button></div>
//给删除附上函数利用filter
</div>
</div>
</div>
<!-- 底部 -->
<div class="bottom">
</div>
</div>
<div class="empty" v-else> 空空如也</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
//水果列表
fruitList: [
{
id: 1,
icon: './img/草莓.png',
isChecked: true,
num: 2,
price: 6,
},
{
id: 2,
icon: './img/香蕉.png',
isChecked: false,
num: 7,
price: 20,
},
{
id: 3,
icon: './img/樱桃.png',
isChecked: true,
num: 2,
price: 6,
}
]
},
methods:{
del(id){
this.fruitList=this.fruitList.filter(item=>item.id!==id)
}
}
})
</script>
全选反选
<style>
* {
margin: 0;
padding: 0;
}
.banner-box {
margin-top: 30px;
margin-left: 400px;
}
.tr {
margin-left: 400px;
width: 500px;
font-size: 20px;
border-left: 15px;
}
.box1 {
padding-right: 10px;
}
.td {
float: left;
width: 72px;
height: 45px;
}
.tractive {
background-color: antiquewhite;
}
.bottom{
float: left;
width: 500px;
margin-left: 400px;
}
</style>
<div class="app-container" id="app">
<!-- 顶部banner -->
<div class="banner-box"><img
src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F7252d6a8-c798-4582-a586-45d3a1b60855%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1708512060&t=8e627cb6e82387038e4a794c5dea2686"
width="500px" height="300px"></div>
<!-- 购物车主体 -->
<div class="main" v-if="fruitList.length>0">
<div class="table">
<!-- 头部 -->
<div class="tr">
<th>
<td class="box1">选中</td>
<td class="box1">图片</td>
<td class="box1">单价</td>
<td class="box1">个数</td>
<td class="box1">小计</td>
<td class="box1">制作</td>
</th>
</div>
</div>
<!-- 身体 -->
<div class="tbody">
<div v-for="(item,index) in fruitList" :key="item.id" class="tr" :class="{active:item.isChecked}">
<div class="td"><input type="checkbox" v-model="item.isChecked"></div>
<div class="td"><img :src="item.icon" width="30px" height="30px"></div>
<div class="td">{{item.price}}</div>
<div class="td">
<div class="my-input-number">
<button :disabled="item.num==1" class="decrease" @click="item.num--">-</button>
<span class="my-input__inner">{{item.num}}</span>
<button class="increase" @click="item.num++">+</button>
</div>
</div>
<div class="td">{{item.num*item.price}}</div>
<div class="td"><button @click="del(item.id)">删除</button></div>
</div>
</div>
</div>
<!-- 底部 -->
<div class="bottom">
<!-- 全选 -->
<label class="check-all">
<input type="checkbox" v-model="isAll">
全选
</label>
<div class="right-box">
<!-- 所有商品总价 -->
<span class="price-box">总价 </span>
<!-- 结算按钮 -->
<button class="pay">结算(6)</button>
</div>
</div>
</div>
<div class="empty" v-else> 空空如也</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
//水果列表
fruitList: [
{
id: 1,
icon: './img/草莓.png',
isChecked: true,
num: 2,
price: 6,
},
{
id: 2,
icon: './img/香蕉.png',
isChecked: false,
num: 7,
price: 20,
},
{
id: 3,
icon: './img/樱桃.png',
isChecked: true,
num: 2,
price: 6,
}
]
},
computed:{
//默认计算属性只能获取不能设置,要设置得完整写法
// isAll(){
// return this.fruitList.every(item=>item.isChecked)
// }
//完整写法=get+set
isAll:{
get(){
return this.fruitList.every(item=>item.isChecked)
},
set(value){
//基于拿到的布尔值,要让所有的小选框 同步状态
this.fruitList.forEach(item =>item.isChecked= value)
//get使上面的小选框控制全选,set使全选控制小选框
}
}
},
methods:{
del(id){
this.fruitList=this.fruitList.filter(item=>item.id!==id)
}
}
})
</script>
统计选中的总价和总数量 计算属性
持久化到本地
<style>
* {
margin: 0;
padding: 0;
}
.banner-box {
margin-top: 30px;
margin-left: 400px;
}
.tr {
margin-left: 400px;
width: 500px;
font-size: 20px;
border-left: 15px;
}
.box1 {
padding-right: 10px;
}
.td {
float: left;
width: 72px;
height: 45px;
}
.tractive {
background-color: antiquewhite;
}
.bottom{
float: left;
width: 500px;
margin-left: 400px;
}
</style>
<div class="app-container" id="app">
<!-- 顶部banner -->
<div class="banner-box"><img
src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F7252d6a8-c798-4582-a586-45d3a1b60855%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1708512060&t=8e627cb6e82387038e4a794c5dea2686"
width="500px" height="300px"></div>
<!-- 购物车主体 -->
<div class="main" v-if="fruitList.length>0">
<div class="table">
<!-- 头部 -->
<div class="tr">
<th>
<td class="box1">选中</td>
<td class="box1">图片</td>
<td class="box1">单价</td>
<td class="box1">个数</td>
<td class="box1">小计</td>
<td class="box1">制作</td>
</th>
</div>
</div>
<!-- 身体 -->
<div class="tbody">
<div v-for="(item,index) in fruitList" :key="item.id" class="tr" :class="{active:item.isChecked}">
<div class="td"><input type="checkbox" v-model="item.isChecked"></div>
<div class="td"><img :src="item.icon" width="30px" height="30px"></div>
<div class="td">{{item.price}}</div>
<div class="td">
<div class="my-input-number">
<button :disabled="item.num==1" class="decrease" @click="item.num--">-</button>
<span class="my-input__inner">{{item.num}}</span>
<button class="increase" @click="item.num++">+</button>
</div>
</div>
<div class="td">{{item.num*item.price}}</div>
<div class="td"><button @click="del(item.id)">删除</button></div>
</div>
</div>
</div>
<!-- 底部 -->
<div class="bottom">
<!-- 全选 -->
<label class="check-all">
<input type="checkbox" v-model="isAll">
全选
</label>
<div class="right-box">
<!-- 所有商品总价 -->
<span class="price-box">总价{{totalPrice}} </span>
<!-- 结算按钮 -->
<button class="pay">结算({{totalCount}})</button>
</div>
</div>
</div>
<div class="empty" v-else> 空空如也</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
//水果列表
fruitList: [
{
id: 1,
icon: './img/草莓.png',
isChecked: true,
num: 2,
price: 6,
},
{
id: 2,
icon: './img/香蕉.png',
isChecked: false,
num: 7,
price: 20,
},
{
id: 3,
icon: './img/樱桃.png',
isChecked: true,
num: 2,
price: 6,
}
]
},
computed:{
//默认计算属性只能获取不能设置,要设置得完整写法
// isAll(){
// return this.fruitList.every(item=>item.isChecked)
// }
//完整写法=get+set
isAll:{
get(){
return this.fruitList.every(item=>item.isChecked)
},
set(value){
//基于拿到的布尔值,要让所有的小选框 同步状态
this.fruitList.forEach(item =>item.isChecked= value)
}
},
//统计选中的总数 reduce
totalCount(){
return this.fruitList.reduce((sum,item)=>{
if(item.isChecked){
//选中->需要累加
return sum+item.num
}else{
//没选中->不需要累加
return sum
}
},0)
},
//统计选中的总价
totalPrice(){
return this.fruitList.reduce((sum,item)=>{
if(item.isChecked) {
return sum+item.num*item.price
}else{
return sum
}
},0)
}
},
methods:{
del(id){
this.fruitList=this.fruitList.filter(item=>item.id!==id)
}
},
watch:{
deep:true,
hander(newValue){
//需要将变化后的newValue存入本地(转JSON)
localStorage.setItem('list',JSON.stringify(newValue))
}
}
})
</script>
</body>