VUE实现购物车(多店铺)

1.效果

也可点链接亲自体验...


瞎封装组件系列:

VUE简单提示框

VUE选择商品多规格(库存判断)

VUE树形图(递归实现)

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>

写的不好,多多指教,开工大吉,牛气冲天!!!

猜你喜欢

转载自blog.csdn.net/m0_43599959/article/details/113858480
今日推荐