电商前台项目:完成加入购物车功能和购物车页面

Posted DantinZhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了电商前台项目:完成加入购物车功能和购物车页面相关的知识,希望对你有一定的参考价值。

Vue2项目前台开发:第五章

一、加入购物车

1.路由跳转前先发请求把商品数据给服务器

(1)观察接口文档

这里其实只需要把已有物品的id和数量传给后台,但是后台不需要返回数据

(2)写接口

点击加入购物车之后要把商品的id和数量传给服务器(数据库的增操作)

src/api/index.js
6.添加到购物车的接口(对已有物品进行数量改动)
地址:/api/cart/addToCart/ skuId / skuNum   post  参数skuId和skuNum
这个请求只需要给服务器发数据,不需要返回什么东西

export const reqShopCarMsg = (skuId, skuNum) => 
    return requests.post(`/cart/addToCart/$skuId/$skuNum`);

(3)dispatch调用接口传数据

1、给加入购物车按钮添加点击事件


2、派送actions,然后把数据以对象的形式传过去,第一个键值对是商品id(当从Search到Detail路由跳转时就传过来的params参数),第二个键值对是购物车数量(我们已经存到了Detail组件的data里)

3、actions这边通过解构赋值,调用接口并把数据传给服务器(后端数据库)

actions: 
        .....
        
        加入购物车
        异步请求,把商品id和数量发送给服务器,参数解构赋值并自己起了个名
        
        async sendShopCarMsg(context,  skuId: id, skuNum: num ) 
            let result = await reqShopCarMsg(id, num);
            //这里只是把购物车数据给服务器,但是服务器不需要返回什么东西
            //所以这里我们不用再三连环了,通过dispatch把数据给服务器就已经欧了
            console.log(result);
        
    ,

(4)判断服务器是否已经收到商品数据

这里要判断请求是否已经成功,也就是服务器是否收到了要加入购物车商品的数据,若成功了就要进行路由跳转并传参,若失败了就要给用户提示。

dispatch就会调用这个actions里的函数,调用这个async函数返回一个promise对象,这个Promise对象的状态和结果值取决于这个async函数的返回值。

1、如果返回一个非Promise对象,那么就是成功,值就是返回值;
2、如果返回Promise对象,那么状态和结果值取决于该Promise
3、如果不写返回值,且await后是失败的Promise,那么就会抛出异常,既然抛出异常,那么async函数返回的就是一个失败的Promise。
4、如果不写返回值,且await后是成功的Promise,那么就会返回undefined,async函数返回的就是一个成功的Promise,值是undefined

如果忘了,去复习Promise:关于Promise的使用和源码

 actions: 
        ....
        调用async函数返回一个promise对象
        //加入购物车
        //异步请求,把商品id和数量发送给服务器,参数解构赋值并自己起名
        async sendShopCarMsg(context,  skuId: id, skuNum: num ) 
           //其实这里不用try-catch,因为那边已经try了,不写return默认返回undefined(成功的Primise)
           //如果await后成功则返回undefined(没写return,返回成功的Promise)
           //如果失败则抛出异常(返回失败的Promise)
            let result = await reqShopCarMsg(id, num);
            //这里只是把购物车数据给服务器,但是服务器不需要返回什么东西
            //所以这里我们不用再三连环了,通过dispatch把数据给服务器就已经欧了
            console.log('zzy',result);
        
    ,

那么这样的话其实就可以使用try-catch来捕获这个返回结果,大概的逻辑是这样的:

//函数3:点击加入购物车把商品数据传给后台服务器的数据库
async sendDataToSql() 
   //1.发请求,把购物车的商品id和数量传给数据库
   try 
     //2.请求成功,服务器已经存储了数据了,那么就要路由跳转并传参
     await this.$store.dispatch('detail/sendShopCarMsg',  skuId: this.$route.params.skuId, skuNum: this.shopCarNum )
     //路由跳转并传参
     // this.$router.push(
     //   name:''
     // )
    catch (error) 
     //3.发送数据(请求)失败,给用户进行提示
     console.log('请求失败了baby', error.message);
   
 

2.请求成功后进行路由跳转

路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹。、

(1)创建路由并配置路由规则

1、所以我们先创建路由

2、配置路由规则src/router/routes.js

(2)路由跳转并传参(练习本地存储)

3、写路由跳转和传参的代码

这里要传两个值:skuInfo对象商品数量shopCarNum(其实skuInfo根本不用传,直接去仓库读就行了)。传参的时候最好别用params和query,因为带过去的需要是skuInfo这个对象,那么对象传过去的话,地址栏可能会是乱码。这里采用的方案是:本地存储(忘了点这先复习)

1、使用query传简单的商品数量shopCarNum,因为数字不会乱码
2、使用会话存储(本地存储也行)带skuInfo过去(其实直接从仓库读就行了;或者你用query也行,无非就是地址栏乱码;这里我们麻烦点,复习复习本地存储)

async sendDataToSql() 
      //1.发请求,把购物车的商品id和数量传给数据库
      try 
        //2.请求成功,服务器已经存储了数据了,那么就要路由跳转并传参
        await this.$store.dispatch('detail/sendShopCarMsg',  skuId: this.$route.params.skuId, skuNum: this.shopCarNum )
        //路由跳转并传参
        this.$router.push(
          name: 'jiaruchenggong',
          query:  shopCarNum: this.shopCarNum   //这里只带购物数量,skuInfo用会话存储
        )
        //比较复杂的skuInfo我们用会话存储传过去
        sessionStorage.setItem('skuInfo', JSON.stringify(this.skuInfo));
       catch (error) 
        //3.发送数据(请求)失败,给用户进行提示
        alert('请求失败了baby', error.message);
      
    

本地存储 里面只能存储字符串格式 ,因此需要把对象转换为字符串JSON.stringify()
获取本地存储数据,需要把里面的字符串转换为对象格式JSON.parse() 我们才能使用里面的数据。


然后把相应的数据放到页面上就欧了


二、完成购物车页面的业务

点击查看商品详情就直接跳回去就行了,数据仓库本来就有不用重新发请求

<router-link class="sui-btn btn-xlarge" to="/detail">查看商品详情</router-link>

接下来是点击去购物车结算,跳到购物车结算页面
把购物车部分的静态搞过来,然后注册一下路由,并写个路由跳转。

<router-link to="/shopcart">去购物车结算 ></router-link>

1.时间戳生成游客id

这里后端应该是写了个逻辑,用一个叫userTempId的请求头字段来定位你是谁,然后返回给你相应的数据。

一般来说正常的逻辑应该是每个用户有自己的token,然后点击加入购物车之后,往用户-商品这个表里添加一行数据;读购物车取数据的时候呢,应该是传用户token参数获取相应的商品列表。而这里为了模拟,后端写好了useTempId字段,刷新时我们就给他个时间戳(唯一id),它就拿着这个字段直接作为本地浏览器游客,所以请求购物车数据也不用传参。

1、进入页面的时候先随机生成一个时间戳,作为用户的id。

export const getId = () => 
    console.log('获取id的函数执行!!!!!')
    let userId = localStorage.getItem('userTempId') || '';
    if(userId) 
       return userId;  
     else 
        localStorage.setItem('userTempId', Date.now());
    

2、请求数据时,在请求拦截器中将该id作为请求中userTempId的值。


3、这样就欧了,只要本地存储中这个id没有被手动清除,那么每次都可以获取该id的购物车数据

2.获取相应的购物车数据

写接口

//7.获取购物车列表数据的接口
// 地址:/api/cart/cartList  GET请求
export const reqShopCartList = () => 
    return requests(
        url: '/cart/cartList',
        method: 'get',
    )

发请求,这里直接看图,就不啰嗦了



最后把数据展示到页面上,比较简单,但是有几个需要注意的地方,见下文:

3.计算打勾商品总价

这个也好算,利用isChecked属性,只计算选中的价格,forEach循环一下就行了

computed: 
  ...mapState('shopcart',['cartList']),
  totalPrice() 
    let totalPrice = 0;
    this.cartList.forEach( el => 
      if(el.isChecked == 1) 
        totalPrice += el.skuNum * el.skuPrice;
      
    );
    return totalPrice;
  
,

4.全选和商品的打勾联动

(1)全选按钮是否选中

isAllChecked() 
   //全选按钮是否选中,取决于每个是否都选中
   return this.cartList.every(el => 
     return el.isChecked == 1;
   )

(2)修改单个产品的选中状态

修改单个产品状态需要去发送请求修改isChecked字段,这是因为总价那里用到了这个字段去计算,我们要实现勾选的计算总价,取消勾选就不计算。
修改产品勾选状态的接口,需要传两个参数

//8.修改产品勾选状态的接口,其实就是拿着id去改isChecked字段
//地址:/api/cart/checkCart/skuID/isChecked  GET
export const changeIsChecked = (skuId, isChecked) => 
    return requests.get(`/cart/checkCart/$skuId/$isChecked`)

vuex调用接口

//2.修改购物车产品的勾选状态
  async changeChecked(context, skuId, state) 
    let result = await changeIsChecked(skuId, state);
    console.log(result);
  

每个购物车商品按钮配置一个点击事件(或者切换事件)如果当前勾选状态为1(勾选),那么改成0(取消勾选),反之也一样。这里要注意参数是skuId,不是id

<ul v-for="good in cartList" :key="good.id" class="cart-list">
   <li class="cart-list-con1">
     <input type="checkbox" name="chk_list" 
     @change="changeState(good.skuId, good.isChecked)" 
     :checked="good.isChecked == 1">
   </li>
   .....
</ul>
<script>
	async changeState(goodId, goodState) 
	   try 
	     //点击某个商品勾选框时,就发请求修改它的勾选状态
	     let stateFlag = goodState == 1 ? 0 : 1; 
	     await this.$store.dispatch('shopcart/changeChecked', id: goodId, state: stateFlag);
	     this.getData();
	   
	   catch(err) 
	     //如果修改失败,那么就提示
	     alert('修改失败!',err);
	   
	 ,
</script>

(3)点击全选时所以商品状态跟着切换

给全选的勾选框添加点击事件。总体来说主要思路就是点击全选时派发请求,这个请求需要把每个商品的勾选状态改成当前全选框的状态。
所以需要在actions中遍历购物车数据并派发请求,(当然其实在组件中写也一样,就是这样规范点),用try-catch捕获,如果都请求成功,那么就使用Promise.all获取成功的标志

  //2.修改购物车产品的勾选状态
  async changeChecked(context, skuId, state) 
    let result = await changeIsChecked(skuId,state);
    console.log('成功',result);
  ,
  //3.点击全选按钮修改其他商品状态
  changeAllStates(dispatch, state, isChecked) 
    let promiseArr = [];
    state.cartList.forEach( el => 
      try 
        let promise = dispatch('changeChecked', skuId: el.skuId, state: isChecked);
        promiseArr.push(promise);
       catch(err) 
        console.log(`$el.skuNam修改失败`,err);
      
    );
    return Promise.all(promiseArr);
  

然后去组件中给全选添加点击事件搞一下就行了,很简单

async selectAllOrNot() 
   let stateFlag = this.isAllChecked ? 0 : 1;
   try 
     let result = await this.$store.dispatch('shopcart/changeAllStates',stateFlag);
     console.log(result);//全是undefined,说明那个请求只写了resolve(),没传值
     this.getData();
    catch(err) 
     console.log('出现错误',err);
   
 ,

5.删除购物车数据

(1)删除单个商品

这个就比较简单了,不多说了,记得写vuex的时候别忘了第一个参数context

这里要注意,这个项目的接口给的都是params参数,而使用axios发请求,params参数只能拼接在url地址中,而query参数的配置项叫params,很奇怪。

接口
//9.删除购物车商品的接口
// /api/cart/deleteCart/skuId
export const reqDeleteGoodById = (skuId) => 
    return requests(
        url: `/cart/deleteCart/$skuId`,
        method: 'delete',
    )

vuex
  //4.删除购物车某条数据,第一个参数别忘了噢
  async deleteOneGood(context,skuId) 
    try
      let result = await reqDeleteGoodById(skuId);
      console.log('删除成功',result);
    catch(err) 
      console.log('错误!!嗷嗷嗷',err)
    
  
组件点击事件
 //4.删除某个购物车商品
  deleteOneGood(skuId) 
    //try-catch捕获一下,如果删除失败,那么就会抛出错误,返回错误的Promise
    //如果删除成功,那么没写返回值返回undefined,默认是成功的Promise
    try 
      this.$store.dispatch('shopcart/deleteOneGood',skuId);
      this.getData();
     catch(err) 
      console.log('删除失败',err)
    
  

(2)删除选中的所有商品

这个逻辑和点击全选修改每个商品的勾选状态是一样的。

1.vuex中利用遍历购物车数据,查出来哪个是选中的,然后依次发请求删除
删除成功与否的结果利用Promise.all传给组件
  //4.删除购物车某条数据,第一个参数别忘了噢
  async deleteOneGood(context,skuId) 
    try
      let result = await reqDeleteGoodById(skuId);
      console.log('删除成功',result);
    catch(err) 
      console.log('错误!!嗷嗷嗷',err)
    
  ,
  //5.删除选中的所有商品
  deleteAllGoods(dispatch,state) 
    //利用Promise.all来给组件反馈成功或失败
    let promiseArr = [];
    state.cartList.forEach(el => 
      if(el.isChecked == 0) return;
      if(el.isChecked == 1)  
        let promise = dispatch('deleteOneGood', el.skuId);
        promiseArr.push(promise);
      
    )
    return Promise.all(promiseArr);
  
2.组件里来个方法,点击删除选中商品按钮生效,方法中派发请求
  //5.删除选中的所有商品
  async deleteAllSelected() 
    //Promise.all返回一个Promise,只有全部成功了才是成功
    try
      await this.$store.dispatch('shopcart/deleteAllGoods');
      this.getData();
    catch(err) 
      console.log('删除过程出现了问题',err.message);
    
  

欧了,搞定

6.购物车商品数量(难点)

(1)分析一下要做什么

这个修改商品数量主要有三个地方,加号、减号、用户输入,那么每改一次实际上都要重新发送请求。这个修改商品数量的接口和加入购物车的接口是一样的。

参数的规则就是传正数代表增加,传负数代表减少,也就是说传的数量skuNum是和原来数量的差值。(盲猜后端写加入购物车时向数据库添加数据默认也是这个规则,只不过初始数量为0,要不然怎么能这俩是一个接口呢?明显改的是一个数据库表)

(2)配置请求的方法

<li class="cart-list-con5">
<!-- ---------------------------------------------------------------- -->
   <!-- 1.减号 -->
    <a href="javascript:void(0)" class="mins" 
    @click="changeSkuNum('sub', good, -1)"<

电商项目测试实战之购物车页面用例设计建议收藏

  购物车页面用例设计

  一、购物车页面

  二、购物车页面测试范围列表

  三、购物车页面功能点需求分析

  四、部分功能点的测试用例设计

  购物车页面

  1、验证添加商品到购物车页面合法,添加成功

  ·步骤描述

  选择不大于20种商品点击加入购物车,再进入我的购物车页面对比选中的商品结果。

  ·测试数据

  商品种类:1种、19种、20种

  ·预期结果

  1)购物车页面显示的商品与添加的商品一致

  2)公共头部购物车角标+1、+19、+20

  3)数据库表tp_cart新增1条/19条/20条记录

  2、验证添加商品到购物车页面种类数非法,添加失败

  ·步骤描述

  选择大于20种商品加入购物车,再进入我的购物车页面对比选中的商品结果。

  ·测试数据

  商品种类:21种

  ·预期结果

  1)在第21种商品添加到购物车时,页面提示购物车种类数已满,添加失败

  2)购物车页面只显示添加的前20种商品信息

  3)公共头部购物车角标+20

  4)数据库表tp_cart新增20条记录

  3、验证添加重复商品到购物车页面合法,添加成功

  ·步骤描述

  选择多个相同商品加入购物车,再进入我的购物车页面对比选中的商品结果。

  ·测试数据

  选择10个Haier/海尔BCD-572WDPM572升对开门电冰箱。

  ·预期结果

  1)购物车页面显示的商品与添加的商品一致

  2)公共头部购物车角标+10

  3)数据库表tp_cart新增10条记录

  4、验证添加商品为空,添加失败

  ·步骤描述

  不选择商品,直接进入购物车页面查看商品情况。

  ·预期结果

  1)购物车页面显示的商品与原先购物车的商品一致

  2)公共头部购物车角标不变

  3)数据库表tp_cart记录不变

  5、验证购物车商品删除后再添加商品到购物车合法,添加成功

  ·步骤描述

  在购物车中删除一个商品,再选择一个商品加入到购物车,进入购物车页面对比选中的商品结果。

  ·预期结果

  1)购物车页面显示的商品与添加的商品一致

  2)公共头部购物车角标先-1后+1

  3)数据库表tp_cart先减少1条记录,后增加一条记录

  6、验证登录前后添加商品到购物车合法,添加成功

  ·步骤描述

  1)登录前,选中商品加入到购物车,在购物车中对比选中的商品结果

  2)登录后,选中商品加入到购物车,在购物车中对比选中的商品结果

  ·测试数据

  选择5个Haier/海尔BCD-572WDPM572升对开门电冰箱。

  ·预期结果

  1)购物车页面显示的商品与添加的商品一致

  2)公共头部购物车角标+5

  3)数据库表tp_cart新增5条记录

  7、验证购物车页面编辑商品数量合法,编辑成功

  ·步骤描述

  在购物车页面中的商品项中改变商品的数量。

  ·测试数据

  1)点击加号/减号编辑商品的数量

  2)手动输入方式编辑商品的数量

  ·预期结果

  前台:

  1)显示编辑后的数据

  2)购物车角标更新

  数据库:tp_cart表goods_num字段的数据更新。

  8、验证购物车页面编辑商品数量长度非法,编辑失败

  ·步骤描述

  在购物车页面中编辑一个商品的数量大于库存数量。

  ·测试数据

  1)点击加号/减号编辑商品的数量大于库存

  2)手动输入方式编辑商品的数量大于库存

  ·预期结果

  页面提示““”超过商品库存”,编辑失败。

  9、验证购物车页面编辑商品数量类型非法,编辑失败

  ·步骤描述

  在购物车页面中编辑一个商品的数量为特殊字符、中文、字母、负数、小数。

  ·测试数据

  编辑数量为:1、特殊字符;2、中文;3、字母;4、负数;5、小数。

  ·预期结果

  页面提示““”数据不合法”,编辑失败。

  10、验证购物车页面编辑商品数量组成非法,编辑失败

  ·步骤描述

  在购物车页面中编辑一个商品的数量组成非正整数。

  ·测试数据

  编辑数量为:1、特殊字符;2、中文;3、字母;4、负数;5、小数。

  ·预期结果

  页面提示““”数据不合法”,编辑失败

  11、验证购物车页面编辑商品数量空非法,编辑失败

  ·步骤描述

  在购物车页面中编辑一个商品的数量为空

  ·测试数据

  商品数量为空

  ·预期结果

  页面提示““”数据为空”,编辑失败

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:包括,软件学习路线图,50多天的上课视频、16个突击实战项目,80余个软件测试用软件,37份测试文档,70个软件测试相关问题,40篇测试经验级文章,上千份测试真题分享,还有2021软件测试面试宝典,还有软件测试求职的各类精选简历,希望对大家有所帮助…

想要获取上方这套学习资料(都是免费获取的~)
添加我们的小姐姐微信即可
可不能撩我们的小姐姐哦

如果对你有帮助的话,点个赞收个藏,给作者一个鼓励。也方便你下次能够快速查找。

以上是关于电商前台项目:完成加入购物车功能和购物车页面的主要内容,如果未能解决你的问题,请参考以下文章

电商项目测试实战之购物车页面用例设计建议收藏

前端静态页面html生活食品电商网站.rar(源码下载-)毕业设计项目

电商的开发流程

前端html静态页面化妆品电商购物网站.rar(含html源码)

Java项目:网上电商系统(java+SSM+mysql+maven+tomcat)

微信小程序结合原生JS实现电商模板