
main.js
// import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
App.vue
<script setup>
import { computed,ref } from 'vue'
//引入产品组件
import ProductVue from './components/Product.vue';
//引入汇总组件
import CollectVue from './components/Collect.vue';
// 购物车中的产品数据
let shopCar = ref([
{
id: 89,
title: '四川爱媛38号果冻橙 当季时令应季彩箱装甜桔橘子新鲜水果专区 净重2斤小果尝鲜装(力荐大果,口感更好更实惠)',
subtitle: '由初逐旗舰店从 四川眉山市 发货, 并提供售后服务. 现在至明日17:00前完成下单,预计11月15日19:30前发货',
image: 'https://img12.360buyimg.com/n1/jfs/t1/39198/22/19565/188868/634a3bc4Ea15f2eee/2bb232b36cdd285c.jpg',
price: 10,
count: 1,
selected: false
},
{
id: 102,
title: '【现货速发】新鲜四季青柠檬 无籽香水柠檬当季生鲜小青柠檬奶茶店水果 有籽青柠檬1斤装试吃【50-80克】',
subtitle: '由朵艾美水果旗舰店发货, 并提供售后服务. 现在至明日16:00前完成下单,预计11月16日23:30前发货',
image: 'https://img12.360buyimg.com/n1/jfs/t1/191077/5/6346/108268/60beea0dEc3a6d2ad/15db7dd619a0bc4f.jpg',
price: 9,
count: 3,
selected: true
},
{
id: 108,
title: '新疆阿克苏冰糖心苹果 新鲜时令水果 阿克苏苹果红富士 10斤礼盒装 单果75-85mm 净重9斤多',
subtitle: '由阿克苏苹果旗舰店发货, 并提供售后服务. 现在至明日16:00前完成下单,预计11月16日20:30前发货',
image: 'https://img13.360buyimg.com/n1/jfs/t1/64647/33/22918/106322/6360afb1E9bab1003/a82bda0aeae6e953.png',
price: 80,
count: 2,
selected: false
}
])
//产品的状态发生改变
function changeShopCarProductChecked(checked,id) {
//循环购物车中的每个产品
shopCar.value.some(product => {
//判断更改的是哪一个产品的checked状态
if(id === product.id) {
product.selected = checked //改变购物车中指定产品的选中的值
return true //结束循环
}
})
}
//产品数量更改
function changeShopCarProductCount(count,id) {
//循环购物车中的每个产品
shopCar.value.some(product => {
//判断更改的是哪一个产品的count
if(id === product.id) {
product.count += count //改变购物车中指定产品的数量
return true //结束循环
}
})
}
//是否全选购物车产品
let isFullSelectProduct = computed(()=>{
return shopCar.value.every(product => product.selected)
})
//改变购物车所有产品的选中状态
function changeShopCarAllProductCheckedState(checked) {
shopCar.value.forEach(product => product.selected=checked)
}
//总金额
let total = computed(()=>{
return shopCar.value.filter(item => item.selected).reduce((money,item)=>(money+=item.price*item.count),0)
})
//购买总数量
let countSum = computed(()=>{
return shopCar.value.filter(item => item.selected).reduce((count,item)=>(count+=item.count),0)
})
</script>
<!-- 视图区域(view) -->
<template>
<!-- 产品组件 -->
<ProductVue
v-for="product in shopCar"
:key="product.id"
:id="product.id"
:picture="product.image"
:title="product.title"
:subtitle="product.subtitle"
:price="product.price"
:count="product.count"
:is-checked="product.selected"
@change-product-checked="changeShopCarProductChecked"
@change-product-count="changeShopCarProductCount"
/>
<hr>
<!-- 使用汇总组件 -->
<CollectVue
:is-all-checked="isFullSelectProduct"
:all-money="total"
:all-count="countSum"
@change-all-checked-state="changeShopCarAllProductCheckedState"
/>
</template>
<style>
* {
margin: 0;
padding: 0;
}
</style>
Product.vue
<script setup>
//声明组件的自定义属性
let propsData = defineProps({
id: {type: Number,required: true}, //产品编号
isChecked: Boolean, //是否被选中
picture: {type: String,required: true}, //图像
title: {type: String,required: true}, //标题
subtitle: {type: String,required: true}, //副标题
price: {type: Number,default: 0}, //单价
count: {type: Number,default: 0} //数量
})
//自定义事件
let emits = defineEmits([
'changeProductChecked', //改变复选框的状态事件
'changeProductCount' //改变产品数量
])
//改变产品选中的状态
function changeCheckedState(e) {
let newCheckedState = e.target.checked //复选框最新的状态
emits('changeProductChecked',newCheckedState,propsData.id) //触发自定义事件,并向父组件传值
}
</script>
<template>
<div class="box">
<!-- 复选框 -->
<input type="checkbox" class="p_checkbox" :checked="isChecked" @change="changeCheckedState">
<!-- 产品图 -->
<img class="p_image" :src="picture">
<!-- 产品内容 -->
<div class="p_content">
<!-- 标题 -->
<h3 class="p_title" v-text="title"></h3>
<!-- 副标题 -->
<span class="p_subtitle" v-text="subtitle"></span>
<!-- 价格 -->
<h2 class="p_price">¥{{ price }}</h2>
<!-- 产品数量区域 -->
<div class="p_count_area">
<button :disabled="count <= 1" @click="emits('changeProductCount',-1,id)">-</button>
<!-- 购买数量 -->
<span v-text="count"></span>
<button @click="emits('changeProductCount',1,id)">+</button>
</div>
</div>
</div>
</template>
<style>
.box {
box-shadow: 0 0 8px gray;
padding: 20px;
margin: 15px;
display: flex;
align-items: center;
}
.p_checkbox {
width: 25px;
height: 25px;
}
.p_image {
width: 120px;
height: 120px;
margin: 0 20px;
}
.p_content {
align-self: start;
position: relative;
width: 100%;
}
.p_title {
margin-bottom: 8px;
}
.p_subtitle {
font-size: 14px;
color: gray;
}
.p_price {
margin-top: 20px;
color: rgb(201,67,67);
}
.p_count_area {
position: absolute;
bottom: 0;
right: 0;
}
.p_count_area button {
width: 25px;
height: 25px;
}
.p_count_area span {
margin: 0 10px;
}
</style>
Collect.vue
<script setup>
//自定义属性
defineProps({
isAllChecked: Boolean, //是否全选
allMoney: {type: Number,default: 0}, //总金额
allCount: {type: Number,default: 0} //总个数
})
//自定义事件
let emits = defineEmits([
'changeAllCheckedState' //改变全选状态的事件
])
</script>
<template>
<div class="container">
<!-- 全选 -->
<label>
<input
type="checkbox"
:checked="isAllChecked"
@change="emits('changeAllCheckedState',$event.target.checked)"
>
全选
</label>
<!-- 总金额 -->
<span>
合计金额:
<strong>¥{{ allMoney }}</strong>
</span>
<!-- 结算按钮 -->
<button>
结算【{{ allCount }}】
</button>
</div>
</template>
<style>
.container {
padding: 20px;
margin: auto 15px;
display: flex;
justify-content: space-between;
align-items: center;
}
.container input {
width: 25px;
height: 25px;
}
.container label {
display: flex;
align-items: center;
width: 70px;
justify-content: space-between;
}
.container strong {
color: red;
}
.container button {
border: none;
padding: 15px 25px;
background-color: rgb(50,140,192);
color: white;
border-radius: 8px;
box-shadow: 0 0 5px gray;
}
</style>
2202

被折叠的 条评论
为什么被折叠?



