From scratch, build a simple shopping platform (17) Front-end mall part

From scratch, build a simple shopping platform (16) Front-end mall part:
https://blog.csdn.net/time_____/article/details/108769229
Project source code (continuous update): https://gitee.com/ DieHunter/myCode/tree/master/shopping

The last article talked about the realization of the product detail page. The last function is to add the shopping cart, that is, to compare whether the product exists through the list. If it exists, modify the existing product data. If it does not exist, initialize the product and add it to In the shopping cart list, this article will introduce the function of operating the shopping cart data

The shopping cart function includes
           modifying the quantity of products, deleting a single product, select all/invert, and delete in bulk

This page is broken down into four components, namely Title at the top, Tabbar on the menu bar, single item shopCarItem and the bulk operation shopCarOrder below

Modifying the number of goods has been introduced in the previous article , and modify it through the countShopItem method

Delete a single product

delShopItem(_id) {
    let _shopCar = this.state//获取现有购物车列表
    _shopCar.splice(_id, 1)//数组删除第_id项
    this.state = _shopCar//刷新购物车列表
    this.$events.emitEvent(EventName.CountShop);//刷新界面
  }

Select all/invert selection, there are two places to pay attention to, the realization of select all/invert selection has two states, one is that each product single selection is selected all or the select all button will follow the state, the other is the select all button All radio buttons will also follow the state after selecting all or unselecting

We first add a method to the action of the store, which is used to total the selected state of the product, the total number of products, and the total price. Whenever the product is selected, this method is triggered to refresh the data

  filterSelect() {//修改商品全选,单个商品驱动全选按钮,刷新数据
    let shopConfig = {//所有商品总计初始值
      _count: 1,//是否全选
      _selCount: 0,//商品总数
      _sum: 0//商品总价
    }
    this.state.forEach(item => {
      shopConfig._selCount += item.isSelect ? 1 : 0;
      shopConfig._count *= item.isSelect;//判断是否全选,初始值0,若全为false,相乘等于0,若全为true,相乘为1,即等于1是全选,等于0是未全选
      shopConfig._sum += item.isSelect ? item.sum : 0
    });
    this.$events.emitEvent(EventName.SelectParent, shopConfig);
  }

In addition, we need to write another method for the select all button to modify the selected state of each product

  selAllChild(_sel) {//修改商品全选,全选按钮驱动单个商品,刷新数据
    this.state = this.state.map(item => {
      item.isSelect = _sel;//当全选按钮选中,修改所有商品状态
      return item;
    });
    this.$events.emitEvent(EventName.SelectAllChild);
  }

So in the single product shopCarItem component, we call the method in the action to modify the global state value

<template>
  <div>
    <ul v-if="shopList.length" class="shopCar">
      <li v-for="(item,index) in shopList" :key="index">
        <span class="mint-checkbox" @click="selectHandler(index)">
          <input class="mint-checkbox-input" type="checkbox" :checked="item.isSelect" />
          <span class="mint-checkbox-core"></span>
        </span>
        <img :src="imgPath+item.shopPic" alt />
        <div class="shopInfo">
          <div>
            <span>{
   
   {item.shopName}} {
   
   {item.shopScale}}克</span>
            <span>¥{
   
   {item.shopPrice}}</span>
          </div>
          <div>
            <mt-button class="minus" type="default" @click="minusShopHandler(item)">-</mt-button>
            <span>{
   
   {item.shopCount}}</span>
            <mt-button class="add" type="default" @click="addShopHandler(item)">+</mt-button>
            <mt-button class="del" type="default" @click="delShopHandler(index)">×</mt-button>
          </div>
        </div>
      </li>
    </ul>
    <div v-else class="noShop">
      <div class="icon-jiarugouwuche iconfont"></div>
      <span>购物车为空</span>
    </div>
  </div>
</template>

<script>
import Config from "../../config/config";
import { Toast } from "mint-ui";
const { EventName } = Config;
export default {
  name: "shopCarItem",
  data() {
    return {
      shopCar: null,//初始化购物车
      shopList: [],//购物车列表state
      imgPath: Config.RequestPath,//静态文件根目录
      selectAll: false,//全选
    };
  },
  created() {
    this.shopCar = new this.$store.ShopCar();
    this.shopList = this.shopCar.state;
    this.$events.onEvent(EventName.CountShop, this.countHandler);//商品数量监听
    this.$events.onEvent(EventName.SelectAllChild, this.selAllHandler);//商品全选监听
  },
  mounted() {
    this.shopCar.filterSelect();//初始化全选,商品数量,商品总价
  },
  destroyed() {
    this.$events.offEvent(EventName.CountShop, this.countHandler);
    this.$events.offEvent(EventName.SelectAllChild, this.selAllHandler);
  },
  methods: {
    countHandler(res) {//修改商品数量,刷新数据
      this.shopList = this.shopCar.state;
      this.shopCar.filterSelect();
    },
    selectHandler(_id) {//修改商品全选,单个商品驱动全选按钮,刷新数据
      this.shopList[_id].isSelect = !this.shopList[_id].isSelect;
      this.shopCar.state = this.shopList;
      this.shopCar.filterSelect();
    },
    selAllHandler() {//修改商品全选,全选按钮驱动单个商品,刷新数据
      this.shopList = this.shopCar.state;
      this.shopCar.filterSelect();
    },
    addShopHandler(_data) {//添加商品,刷新数据
      _data.shopCount = 1;
      this.shopCar.countShopItem({
        ..._data,
      });
    },
    minusShopHandler(_data) {//减少商品,刷新数据
      _data.shopCount = -1;
      this.shopCar.countShopItem({
        ..._data,
      });
    },
    delShopHandler(_id) {//删除单个商品,刷新数据
      this.shopCar.delShopItem(_id);
    },
  },
};
</script>

<style lang="less" scoped>
@import "../../style/init.less";
.noShop {
  width: 100%;
  height: 100%;
  text-align: center;
  span {
    .f_s(36);
  }
  div {
    .w(200);
    .h(200);
    border-radius: 100%;
    background: @mainColor;
    .titleFont();
    box-shadow: 5px 5px 8px #777;
    .l_h(200);
    text-align: center;
    margin: 100px auto 20px;
    .f_s(100);
  }
}
.shopCar {
  .padbottom(130);
  width: 100%;
  li {
    border-bottom: 1px solid #d3d3d3;
    padding-left: unit(35 / @pxtorem, rem);
    .h(320);
    .mint-checkbox {
      .h(320);
      .l_h(320);
      display: inline-block;
      vertical-align: middle;
    }
    .mint-checkbox-input:checked + .mint-checkbox-core {
      background: #ea3e3c;
      border-color: #ea3e3c;
    }
    img {
      .h(265);
      .w(265);
      margin-left: unit(20 / @pxtorem, rem);
      display: inline-block;
      vertical-align: middle;
      background: #f5f6f5;
    }
    .shopInfo {
      .h(235);
      width: 50%;
      .padtop(30);
      padding-left: unit(10 / @pxtorem, rem);
      display: inline-block;
      vertical-align: middle;
      div:nth-child(1) {
        overflow: hidden;
        span {
          float: left;
        }
        span:nth-child(2) {
          float: right;
        }
      }
      div:nth-child(2) {
        margin-top: unit(85 / @pxtorem, rem);
        span {
          display: inline-block;
          vertical-align: middle;
          padding: 0 unit(50 / @pxtorem, rem);
        }
        .add,
        .minus,
        .del {
          display: inline-block;
          vertical-align: middle;
          background: white;
          box-shadow: none;
          .f_s(50);
        }
        .del {
          float: right;
        }
      }
    }
  }
}
</style>

The same in batch operation shopCarOrder component

<template>
  <div class="shopOrder">
    <span class="mint-checkbox" @click="selectHandler">
      <input class="mint-checkbox-input" type="checkbox" :checked="isSelAll" />
      <span class="mint-checkbox-core"></span>
    </span>
    <span>全选({
   
   {selCount}})</span>
    <span @click="delSelShop">删除({
   
   {selCount}})</span>
    <span>
      <span>¥{
   
   {sum}}</span>
      <span class="icon-qianjin iconfont" @click="sendOrder"></span>
    </span>
  </div>
</template>

<script>
import Config from "../../config/config";
import ShopCarOrderBussiness from "./bussiness";
import { Toast } from "mint-ui";
const { EventName } = Config;
export default {
  name: "shopCarOrder",
  data() {
    return {
      shopCar: null,
      isSelAll: false,//全选
      selCount: 0,//商品数量
      sum: 0,//商品总价
      orderList: null,//提交订单请求参数
      shopCarOrderBussiness: null,
    };
  },
  created() {
    this.shopCar = new this.$store.ShopCar();
    this.shopCarOrderBussiness = new ShopCarOrderBussiness(this);
    this.$events.onEvent(EventName.SelectParent, this.selAllHandler);//全选按钮监听,通过监听所有商品都选中或未全选,修改状态
  },
  destroyed() {
    this.$events.offEvent(EventName.SelectParent, this.selAllHandler);
  },
  methods: {
    selectHandler() {//驱动修改所有商品选中状态
      this.isSelAll = !this.isSelAll;
      this.shopCar.selAllChild(this.isSelAll);
    },
    selAllHandler({ _count, _selCount, _sum }) {
      this.isSelAll = _count;
      this.selCount = _selCount;
      this.sum = _sum;
    },
    delSelShop() {//删除选中商品
      this.shopCar.delSelShop();
    },
    sendOrder() {//提交订单
      this.shopCarOrderBussiness.sendOrderList();
    },
  },
};
</script>

<style lang="less" scoped>
@import "../../style/init.less";
.shopOrder {
  .f_s(34);
  color: #fff;
  position: fixed;
  .mcolor();
  bottom: unit(130 / @pxtorem, rem);
  width: 100%;
  .h(130);
  .l_h(130);
  > span:nth-child(1),
  > span:nth-child(2) {
    padding-left: unit(35 / @pxtorem, rem);
  }
  > span:nth-child(3) {
    padding-left: unit(200 / @pxtorem, rem);
  }

  > span:nth-child(4) {
    float: right;
    margin-right: unit(50 / @pxtorem, rem);
    > span:nth-child(1) {
      padding-left: unit(20 / @pxtorem, rem);
      border-left: 1px dashed #fff;
    }
    > span:nth-child(2) {
      padding-left: unit(50 / @pxtorem, rem);
    }
  }
  > span {
    display: inline-block;
  }
  .mint-checkbox-input + .mint-checkbox-core {
    background: transparent;
    border-color: #fff;
  }
  .mint-checkbox-input:checked + .mint-checkbox-core {
    .mcolor();
  }
}
</style>

In action, we also need to write a function to delete the selected product

delSelShop() {//直接通过遍历商品选中状态值进行删除,并刷新数据
    let _list = []
    this.state.map(item => {
      if (!item.isSelect) {
        _list.push(item)
      }
    });
    this.state = _list
    this.$events.emitEvent(EventName.CountShop);
  }

Finally, these four components are introduced into the shopCar.vue interface, and the page implementation is complete

<template>
  <div>
    <Top title="购物车"></Top>
    <div class="content">
      <ShopCarItem></ShopCarItem>
      <ShopCarOrder></ShopCarOrder>
    </div>
    <TabBar></TabBar>
  </div>
</template>

<script>
import Top from "../../components/top/top";
import ShopCarItem from "../../components/shopCarItem/shopCarItem";
import ShopCarOrder from "../../components/shopCarOrder/shopCarOrder";
import TabBar from "../../components/tabBar/tabBar";
export default {
  name: "shopCar",
  data() {
    return {};
  },
  components: {
    Top,
    ShopCarItem,
    ShopCarOrder,
    TabBar
  },
  created() {}
};
</script>
<style lang="less" scoped>
@import "../../style/init.less";
</style>

This article mainly introduces the operation of the product shopping cart, which uses the basic operation of data refresh view, separates the data, logic, and view, and combines the data binding of vue to render the page. The next article will implement user registration and login functions (simple username and password registration, login, and email verification modules)

Guess you like

Origin blog.csdn.net/time_____/article/details/108893925