从零开始,搭建一个简单的购物平台十七前端商城部分

从零开始,搭建一个简单的购物平台(十六)前端商城部分:
https://blog.csdn.net/time_____/article/details/108769229
项目源码(持续更新):https://gitee.com/DieHunter/myCode/tree/master/shopping

上篇文章讲到了商品详情页面实现,最后一个功能是加入购物车,也就是通过列表对比商品是否存在,若存在,则对现有商品数据进行修改,若不存在,则初始化商品,并添加至购物车列表中,这篇文章将介绍对购物车数据进行操作功能

购物车功能包括
           修改商品数量                        删除单个商品                           全选/反选                               批量删除

这个页面,将其分解成四个组件,分别是顶部的Title,菜单栏Tabbar,单件商品shopCarItem和下面的批量操作shopCarOrder

修改商品数量在上篇文章中已介绍,通过countShopItem方法进行修改

删除单个商品

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

全选/反选,这里有两个注意的地方,全选/反选的实现有两种状态,一是每个商品单选被全选或反选后全选按钮也会跟随状态,二是全选按钮全选或反选后所有单选按钮也会跟随状态

我们首先在store的action加一个方法,用于总计商品的全选状态,商品总数,及总价格。每当商品被选中,就触发这个方法,刷新数据

  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);
  }

此外,我们需要再写个方法,用于全选按钮修改各个商品的选中状态

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

于是在单件商品shopCarItem组件中,我们进行调用action中的方法,修改全局state值

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

在批量操作shopCarOrder组件中同理

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

在action中,我们还需要写一个函数,用于删除选中商品

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

最后,在shopCar.vue界面中引入这四个组件,页面实现完成

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

本篇文章主要对商品购物车操作进行了介绍,其中运用了数据刷新视图的基本操作,将数据,逻辑,视图三者分开,结合vue的数据绑定渲染页面。下篇文章将实现用户的注册,登录功能(简单的用户名密码注册,登录,和邮箱验证模块)

原文地址:https://blog.csdn.net/time_____

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于nodejs...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs怎么实现目录不存在自动创建”文章能帮助大...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs如何实现定时删除文件”文章能帮助大家解决疑惑...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文...
本篇内容主要讲解“怎么安装Node.js的旧版本”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎...
这篇“node中的Express框架怎么安装使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要介绍“nodejs如何实现搜索引擎”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs如何实现搜索引擎...
这篇文章主要介绍“nodejs中间层如何设置”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs中间层如何设置”文...
这篇文章主要介绍“nodejs多线程怎么实现”,在日常操作中,相信很多人在nodejs多线程怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
这篇文章主要讲解了“nodejs怎么分布式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodejs怎么分布式”...
本篇内容介绍了“nodejs字符串怎么转换为数组”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情...
这篇文章主要介绍了nodejs如何运行在php服务器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇nodejs如何运行在php服务器文章都...
本篇内容主要讲解“nodejs单线程如何处理事件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“nodejs单线程如何...
这篇文章主要介绍“nodejs怎么安装ws模块”,在日常操作中,相信很多人在nodejs怎么安装ws模块问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
本篇内容介绍了“怎么打包nodejs代码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!
本文小编为大家详细介绍“nodejs接收到的汉字乱码怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs接收到的汉字乱码怎么解决”文章能帮助大家解...
这篇“nodejs怎么同步删除文件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇...
今天小编给大家分享一下nodejs怎么设置淘宝镜像的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希