1.效果
也可点链接亲自体验...
瞎封装组件系列:
2.代码实现
<template>
<div class="goodscart">
<div class="goods_box">
<div style="position: fixed;left: 0;top: 0;color: red;display: none;">{
{checkgoodslist}}</div>
<div class="shop_item" v-for="(item,index) in goods">
<div class="shop_name flex-between">
<div class="shop_name_left flex-star">
<input @click="checkshop(index)" v-model="item.ischeck" type="checkbox" />
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-shangcheng"></use>
</svg>
<span>{
{item.shopname}}</span>
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-right"></use>
</svg>
</div>
</div>
<div class="goods_list flex-star" v-for="(goodsitem,goodsindex) in item.goodslist">
<input @click="checkgoods(index,goodsindex)" v-model="goodsitem.ischeck" type="checkbox" />
<img :src="goodsitem.goodsimg">
<div class="good_item_more">
<div class="wordNoWarp">
{
{goodsitem.goodsname}}
</div>
<div class="gui_ge">
<span v-for="spec in goodsitem.goodsspec">{
{spec}}</span>
</div>
<div class="flex-between">
<div class="priceitem_box">¥<span class="goods_price">{
{goodsitem.price}}</span></div>
<div class="opt_box flex-star">
<div class="reduce" @click="numreduce(index,goodsindex)">-</div>
<div class="goods_num">{
{goodsitem.num}}</div>
<div class="add" @click="numadd(index,goodsindex)">+</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="page_bottom flex-between">
<div class="flex-star">
<input class="check_all" v-model="checkall" @click="claickcheckall" type="checkbox" />
<span>全选</span>
</div>
<div class="flex-star">
<span>总计:</span>
<span class="allprice">{
{allprice}}</span>
<input class="page_btn page_btn_act" type="button" name="" id="" value="结算" />
<input class="page_btn" type="button" name="" id="" value="删除" />
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
checkall: false,
}
},
props: {
goods: {
type: Array,
required: true
},
isAllCheck: {
type: Boolean,
default: false
}
},
components: {},
methods: {
// 数量加减
numadd(shopindex, goodsindex) {
if (this.goods[shopindex].goodslist[goodsindex].num < this.goods[shopindex].goodslist[goodsindex].maxnum) {
this.goods[shopindex].goodslist[goodsindex].num++;
}
},
numreduce(shopindex, goodsindex) {
if (this.goods[shopindex].goodslist[goodsindex].num > 1) {
this.goods[shopindex].goodslist[goodsindex].num--;
} else {
this.$tips({
msg: "至少选一件",
flag: true
});
}
},
// 单商品勾选
checkgoods(shopindex, goodsindex) {
let length = 0;
let length2 = 0;
this.goods[shopindex].goodslist[goodsindex].ischeck = !this.goods[shopindex].goodslist[goodsindex].ischeck;
this.goods[shopindex].goodslist.forEach(item => {
if (item.ischeck) {
length++
}
})
if (this.goods[shopindex].goodslist.length == length) {
this.goods[shopindex].ischeck = true;
} else {
this.goods[shopindex].ischeck = false;
}
this.goods.forEach(item => {
if (item.ischeck) {
length2++;
}
})
if (this.goods.length === length2) {
this.checkall = true
} else {
this.checkall = false
}
},
// 商店勾选
checkshop(shopindex) {
this.goods[shopindex].ischeck = !this.goods[shopindex].ischeck;
if (this.goods[shopindex].ischeck) {
this.goods[shopindex].goodslist.forEach(item => {
item.ischeck = true;
})
} else {
this.goods[shopindex].goodslist.forEach(item => {
item.ischeck = false;
})
}
let length = 0;
this.goods.forEach(item => {
if (item.ischeck) {
length++;
}
})
if (length === this.goods.length) {
this.checkall = true;
} else {
this.checkall = false;
}
},
// 全选
claickcheckall() {
if (!this.checkall) {
this.goods.forEach(item => {
item.ischeck = true;
item.goodslist.forEach(goodsitem => {
goodsitem.ischeck = true;
})
})
} else {
this.goods.forEach(item => {
item.ischeck = false;
item.goodslist.forEach(goodsitem => {
goodsitem.ischeck = false;
})
})
}
}
},
computed: {
// 计算总价
allprice() {
let price = 0;
this.goods.forEach(item => {
item.goodslist.forEach(goodsitem => {
if (goodsitem.ischeck) {
price += goodsitem.price * goodsitem.num;
}
})
})
return "¥" + price.toFixed(2);
},
// 统计勾选商品
checkgoodslist() {
let calcheckgoods = [];
this.goods.forEach(item => {
item.goodslist.forEach(goodsitem => {
if (goodsitem.ischeck) {
calcheckgoods.push(goodsitem);
}
})
})
console.log(calcheckgoods)
return calcheckgoods;
}
}
}
</script>
<style scoped="scoped">
.goods_box {
color: #333;
height: calc(100vh - 3.8rem);
overflow-y: scroll;
}
.goods_list {
padding: .2rem;
}
.goods_list img {
width: 1.8rem;
height: 1.8rem;
margin: 0 .15rem;
border-radius: 5px;
}
.good_item_more {
width: calc(100% - 2.8rem);
height: 1.8rem;
}
.good_item_more .wordNoWarp {
-webkit-line-clamp: 2;
}
.priceitem_box {
color: #333;
font-weight: bold;
}
.goods_price {
font-size: .34rem;
}
.opt_box div {
width: .4rem;
height: .4rem;
border: 1px solid #999;
text-align: center;
line-height: .4rem;
border-radius: 4px;
}
.opt_box div:nth-child(2) {
border: none;
width: .5rem;
text-align: center;
}
.opt_box div:nth-child(3) {
background: #333;
color: white;
border: none;
}
.shop_item {
margin: 0 .24rem 0 .24rem;
border-radius: 8px;
overflow: hidden;
background: white;
}
.goods_box .shop_item:nth-child(n + 2) {
margin-top: .2rem;
}
.shop_name {
border: 1px solid #f2f2f2;
padding: .2rem;
}
.goods_box {
border-radius: 8px;
}
.page_bottom {
background: white;
position: fixed;
bottom: 0;
left: 0;
padding: .15rem .25rem;
width: 100%;
}
.page_btn {
display: none;
width: 2.8rem;
height: .8rem;
border-radius: .8rem;
background: #333;
border: none;
color: white;
font-size: .32rem;
}
.page_btn_act {
display: block;
}
.allprice {
color: #333;
font-weight: bold;
margin-right: .2rem;
font-size: .4rem;
}
.shop_name svg:nth-child(2) {
margin-right: .1rem;
}
.address_box a {
color: #aaa;
}
.gui_ge {
padding: .1rem 0;
}
.gui_ge span {
display: inline-block;
font-size: .1rem;
color: #999;
}
.gui_ge span:nth-child(n + 2)::before {
content: ";";
}
.shop_name_left {
color: #999;
}
</style>
3.使用
使用要求,组件规定必须传入一个存储商品信息的数组和是否全选(购物车总商品全选)。
存储商品信息的数组的元素是json,必须符合规范(就如案例所示):
<template>
<div class="ui-pane">
<ui-header headertit="购物车组件"></ui-header>
<div class="ui-content">
<div class="page_tit flex-between">
<div>购物车</div>
<span class="manage">管理</span>
</div>
<div class="page_address flex-star">
<div class="goods_num_box">
共3件宝贝
</div>
<div class="address_box">
收货地址:重庆市南岸区南城...
</div>
</div>
<imglist :goods="goods"></imglist>
</div>
</div>
</template>
<script>
import imglist from '../../../../components/goodscart/goodscart.vue'
export default {
data() {
return {
isShow: false,
goods: [{
ischeck: false,
shopname: '南方大米官方自营店',
goodslist: [{
ischeck: false,
goodsimg: 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3447506328,3763843571&fm=26&gp=0.jpg',
goodsname: '芳姐卤香干 600g湖南特产武冈 卤豆腐豆干制品休闲素食零...',
goodsspec: ['包邮', '麻辣'],
price: '99.50',
maxnum: 100,
num: 1
}]
}, {
ischeck: false,
shopname: '南方大米官方自营店',
goodslist: [{
ischeck: false,
goodsimg: 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=249803900,574094454&fm=11&gp=0.jpg',
goodsname: '芳姐卤香干 600g湖南特产武冈 卤豆腐豆干制品休闲素食零...',
goodsspec: ['包邮', '麻辣'],
price: '88.40',
maxnum: 100,
num: 1
}, {
ischeck: false,
goodsimg: 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3045272867,3557946177&fm=26&gp=0.jpg',
goodsname: '芳姐卤香干 600g湖南特产武冈 卤豆腐豆干制品休闲素食零...',
goodsspec: ['包邮', '麻辣'],
price: '77.66',
maxnum: 10,
num: 1
}]
}],
}
},
components:{
imglist
}
}
</script>
<style scoped="scoped">
.page_tit {
height: 1rem;
padding: 0 .24rem;
color: #333;
}
.page_tit div {
font-size: .36rem;
font-weight: bold;
color: #333;
}
.page_address {
height: .3rem;
font-size: .24rem;
padding: 0 .24rem;
margin-bottom: .2rem;
}
.address_box {
margin-left: .2rem;
}
</style>
写的不好,多多指教,开工大吉,牛气冲天!!!