VUE realizes shopping cart (multi-store)

1. Effect

You can also click the link to experience it yourself...


Blind package component series:

 

VUE simple prompt box

VUE selects multiple specifications of products (inventory judgment)

VUE tree diagram (recursive implementation)

 

 

2. Code implementation

<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. Use

Usage requirements, the component stipulates that an array of stored product information must be passed in and whether to select all (select all products in the shopping cart).

The element of the array storing the product information is json, which must conform to the specification (as shown in the case):

<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>

Poor writing, give me a lot of advice, start working, and be bullish! ! !

Guess you like

Origin blog.csdn.net/m0_43599959/article/details/113858480