② 尚品汇的前台开发笔记【尚硅谷】【Vue】

文章目录

  • 八、加入购物车
    • 路由跳转之前发请求
      • api---请求接口
      • 将数据存储到服务器里
      • 判断加入成功 或 失败
    • 成功后进行路由跳转
      • 开始进行路由跳转,并进行路由传参
      • 开始渲染页面
      • 购物车静态组件与修改
  • 九、完成ShopCart购物车模块业务
    • 向服务器发起请求,获取购物车数据
      • 向服务器发请求
      • 操作vuex 将数据存储到仓库中
      • 组件获取数据展示数据
    • UUID临时游客身份
    • 动态展示购物车
      • 修改购物车产品的数量
      • 删除购物车产品
      • 修改产品的勾选状态
      • 删除选中全部产品的操作
      • 修改全部商品的勾选状态
  • 十、完成登录与注册页面

八、加入购物车

点击 加入购物车 的时候,先发请求,把数据存储到服务器,然后再进行路由跳转

② 尚品汇的前台开发笔记【尚硅谷】【Vue】_第1张图片

  • 当点击 加入购物车 的时候,会跳转到 加入购物车成功的页面,到时候需要配置路由,进行路由跳转
    ② 尚品汇的前台开发笔记【尚硅谷】【Vue】_第2张图片

路由跳转之前发请求

api—请求接口

//     src/api/index.js

// 将产品添加到购物车中(或者 更新某一个产品个数)
//   /api/cart/addToCart/{ skuId }/{ skuNum }  POST 带参数
export const reqAddOrUpdateShopCart = (skuId,skuNum)=>{
    return requests({url:`/cart/addToCart/${skuId}/${skuNum}`,method:'POST'})
}

将数据存储到服务器里

  1. 派发actions,发请求

    //       src / pages / detail /index.vue
    
    <div class="add">
     
     
          <a @click="addShopcar">加入购物车a>
    div>
    
        // 加入购物车的回调函数
    addShopcar() {
          // 1. 发请求--将产品加入到数据库(通知服务器)
          //    服务器存储成功----进行路由跳转
          //    失败,给用户提示
         this.$store.dispatch( "detail/addOrUpdateShopCart",{skuId:this.$route.params.skuId,skuNum:this.skuNum});
    },
    

加入购物车以后(发请求),前台将参数带给服务器

服务器写入数据成功,并没有返回其他的数据,只是返回code=200,代表这次成功

⚠ !!!因为服务器没有返回其余的数据,所以我们不需要vuex来存储数据

  1. 将参数带给服务器

    const actions = {
        // 将产品添加到购物车中
        async addOrUpdateShopCart({commit},{skuId,skuNum}){
            // 加入购物车返回的结果
            let result = await reqAddOrUpdateShopCart(skuId,skuNum);
            console.log('购物车',result);
            // 加入购物车以后(发请求),前台将参数带给服务器
            // 服务器写入数据成功,并没有返回其他的数据,只是返回code=200,代表这次成功
            // 因为服务器没有返回其余的数据,所以我们不需要vuex来存储数据
        },
    };
    

判断加入成功 或 失败

async:只要有async返回的就是Promise,Promise返回的不是成功就是失败

  1. 发请求–将产品加入到数据库(通知服务器)

  2. 服务器存储成功----进行路由跳转

  3. 服务器存储失败------给用户提示

//      src/pages/detail/index.vue

	// 加入购物车的回调函数
    async addShopcar() {
      // 1. 发请求--将产品加入到数据库(通知服务器)
      //    服务器存储成功----进行路由跳转
      //    失败------给用户提示
      try {
        await this.$store.dispatch("detail/addOrUpdateShopCart", {skuId: this.$route.params.skuId,skuNum: this.skuNum,});
        // 成功了进行路由跳转
          .....
      } catch (error) {
        alert(error.message);
      }
    },

this.$store.dispatch("detail/addOrUpdateShopCart", {skuId: this.$route.params.skuId,skuNum: this.skuNum,});表示调用了addOrUpdateShopCart这个函数,调用这个函数,这个函数有async,说明这个函数的返回值是Promise函数

await返回的是promise成功的值,但是我们要有成功做什么以及失败做什么…如果await的promise失败了,就会抛出异常,我们需要通过try…catch捕获处理

所以在detail.vue中,给 加入购物车的回调函数加上 async

//      src/store/detail/index.js

	// 将产品添加到购物车中
    async addOrUpdateShopCart({ commit }, { skuId, skuNum }) {
        // 加入购物车返回的结果
        // 加入购物车以后(发请求),前台将参数带给服务器
        // 服务器写入数据成功,并没有返回其他的数据,只是返回code=200,代表这次成功
        // 因为服务器没有返回其余的数据,所以我们不需要vuex来存储数据
        let result = await reqAddOrUpdateShopCart(skuId, skuNum);
        // 当前的这个函数,如果执行,返回promise
        // 代表服务器加入购物车成功
        if(result.code==200){
            return 'ok'; // 返回的只要是非空字符串就是成功
        }else{
            // 代表加入购物车失败
            return Promise.reject(new Error('false'));
        }
    },

成功后进行路由跳转

注意:路由不是组件!!!??????❓

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

使用组件的步骤:创建-注册-引用-使用

  1. 创建路由,写到专门放路由的文件夹下

    ② 尚品汇的前台开发笔记【尚硅谷】【Vue】_第3张图片

  2. 编写路由配置项:src/router/index.js

    // 配置路由的地方
    import Vue from 'vue';
    import VueRouter from 'vue-router';
    // 使用插件
    Vue.use(VueRouter);
    
    // 引入路由组件
    import AddCartSuccess from '../pages/AddCartSuccess'
    
    // 先把VueRouter原型对象的push,先保存一份
    const originalPush = VueRouter.prototype.push
    const originalReplace = VueRouter.prototype.replace
    
    // 重写push | replace
    // 参数:告诉原来的push方法,你往哪里跳转(传递哪些参数)
    VueRouter.prototype.push = function push(location) {
        return originalPush.call(this, location).catch(err => err)
    }
    VueRouter.prototype.replace = function replace(location) {
        return originalReplace.call(this, location).catch(err => err)
    }
    
    // 配置路由
    export default new VueRouter({
        // 配置路由
        routes: [
            ...
            {
                name: 'addcartsuccess',
                path: '/addcartsuccess',
                component: AddCartSuccess,
                meta: { showFooter: true }
            },
            // 重定向:在项目跑起来的时候,访问/,立马让他定向到首页!!!
            {
                path: '*',
                redirect: '/home',
            }
        ],
        // 控制滚动条的滚动行为
        scrollBehavior(to, from, savedPosition) {
            // return 期望滚动到哪个的位置
            return { y: 0 }; // 始终滚动到顶部
        }
    })
    

开始进行路由跳转,并进行路由传参

② 尚品汇的前台开发笔记【尚硅谷】【Vue】_第4张图片

路由传参的话数据过多,在skuInfo里面,是个对象,以及还要带参数skuNum,地址栏会有点乱

② 尚品汇的前台开发笔记【尚硅谷】【Vue】_第5张图片

所以这里我们只带skuNum参数传过去,其余复杂数据用会话存储—不持久化,会话结束数据消失

浏览器存储功能:HTML5中新增的,分为本地存储和会话存储

本地存储:持久化的,具有上限-----5M

会话存储:不是持久化的(浏览器关闭等),

② 尚品汇的前台开发笔记【尚硅谷】【Vue】_第6张图片

    // 加入购物车的回调函数
    async addShopcar() {
      // 1. 发请求--将产品加入到数据库(通知服务器)
      //    服务器存储成功----进行路由跳转
      //    失败------给用户提示
      try {
        await this.$store.dispatch("detail/addOrUpdateShopCart", {
          skuId: this.$route.params.skuId,
          skuNum: this.skuNum,
        });
        // 成功了进行路由跳转,并将产品的信息带给下一级的路由组件
        // 会话存储 | 本地存储,一般存储的是字符串,所以将对象转换为字符串
        sessionStorage.setItem('SKUINFO',JSON.stringify(this.skuInfo))
        this.$router.push({
          name: "addcartsuccess",
          query:{skuNum:this.skuNum},
        });
      } catch (error) {
        alert(error.message);
      }
    },

本地存储 里面只能存储字符串格式 ,因此需要把对象转换为字符串JSON.stringify()

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

获取本地存储数据

② 尚品汇的前台开发笔记【尚硅谷】【Vue】_第7张图片

开始渲染页面

   <div class="left-good">
         <div class="left-pic">
            <img :src="skuInfo.skuDefaultImg" />
         div>
         <div class="right-info">
            <p class="title">{{ skuInfo.skuName }}p>
            <p class="attr">
              <span v-for="attrName in skuInfo.skuSaleAttrValueList" :key="attrName.id">{{ attrName.saleAttrName }} {{attrName.saleAttrValueName}}  span>
              <span>数量:{{$route.query.skuNum}}span>
            p>
         div>
       div>
   <div class="right-gocart">

在这里插入图片描述

购物车静态组件与修改

② 尚品汇的前台开发笔记【尚硅谷】【Vue】_第8张图片

  1. 跳转到detail商品详情页,携带参数

     <div class="right-gocart">
              <router-link :to="`/detail/${skuInfo.id}`" class="sui-btn btn-xlarge">查看商品详情router-link>
              <a href="javascript:">去购物车结算 > a>
     div>
    
  2. 跳转到购物车页面ShopCart

九、完成ShopCart购物车模块业务

image-20220810195327300

  1. 引入和配置路由

    // 配置路由的地方
    import Vue from 'vue';
    import VueRouter from 'vue-router';
    // 使用插件
    Vue.use(VueRouter);
    
    // 引入路由组件
    import ShopCart from '../pages/ShopCart'
    
    // 先把VueRouter原型对象的push,先保存一份
    const originalPush = VueRouter.prototype.push
    const originalReplace = VueRouter.prototype.replace
    
    // 重写push | replace
    // 参数:告诉原来的push方法,你往哪里跳转(传递哪些参数)
    VueRouter.prototype.push = function push(location) {
        return originalPush.call(this, location).catch(err => err)
    }
    VueRouter.prototype.replace = function replace(location) {
        return originalReplace.call(this, location).catch(err => err)
    }
    
    // 配置路由
    export default new VueRouter({
        // 配置路由
        routes: [
            {
                name: 'shopcart',
                path: '/shopcart',
                component: ShopCart,
                meta: { showFooter: true },
            },
            // 重定向:在项目跑起来的时候,访问/,立马让他定向到首页!!!
            {
                path: '*',
                redirect: '/home',
            }
        ],
        // 控制滚动条的滚动行为
        scrollBehavior(to, from, savedPosition) {
            // return 期望滚动到哪个的位置
            return { y: 0 }; // 始终滚动到顶部
        }
    })
    
  2. 路由跳转

      
    查看商品详情 去购物车结算 >

向服务器发起请求,获取购物车数据

向服务器发请求

/api/cart/cartList GET 无参数

//    src/api/index.js

// 获取购物车列表数据   /api/cart/cartList  GET 无参数
export const reqCartList = ()=>{
    return requests({url:'/cart/cartList',method:'GET'})
}

操作vuex 将数据存储到仓库中

  1. 新建一个仓库,用来存储购物车的数据
//      src/store/shopcart/index.js

import { reqCartList } from '@/api/index'
const state = {};
const mutations = {};
const actions = {};
const getters = {};
export default {
    namespaced: true,
    state,
    mutations,
    actions,
    getters
}
  1. 在大仓库中引用小仓库
//      src/store/index.js

import Vue from 'vue';
import Vuex from 'vuex';
// 需要使用插件
Vue.use(Vuex);

// 引入小仓库
import home from './home'
import search from './search'
import detail from './detail'
import shopcart from './shopcart';
// 对外暴露Store类的一个实例
export default new Vuex.Store({
    // 实现vuex仓库模块式开发存储数据
    modules:{
        home,
        search,
        detail,
        shopcart
    }
})
  1. vuex三连环

    const actions = {
        // 获取购物车列表的数据
        async getCartList({ commit }) {
            let result = await reqCartList();
            console.log('购物车列表',result);
        },
    };
    
      export default {
        name: 'ShopCart',
        mounted(){
          // 获取服务器数据
          this.getData();
        },
        methods:{
          // 获取个人购物车数据
          getData(){
            this.$store.dispatch('shopcart/getCartList');
          }
        }
      }
    

    注意:发请求的时候,获取不到你购物车里的数据,因为这里不知道购物车获取谁的数据,需要给用户加一个身份!所以需要 UUID临时游客身份

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEtvGoZp-1662259079858)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220808200759898.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ACdKJbHu-1662259079859)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220808201000762.png)]

  2. 开始真正的vuex三连环!!

    这个是shopcart仓库里面的数据,有点复杂,所以我们要简化

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Of4Utzy-1662259079860)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220808201439581.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4i69LqhO-1662259079860)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220808202719439.png)]

    import { reqCartList } from '@/api/index'
    
    const state = {
        cartList:[],
    };
    
    const mutations = {
        GETCARTLIST(state, cartList) {
            state.cartList = cartList;
        }
    };
    
    const actions = {
        // 获取购物车列表的数据
        async getCartList({ commit }) {
            let result = await reqCartList();
            if (result.code == 200) {
                commit('GETCARTLIST', result.data); // result.data 是个数组
            }
        },
    };
    
    const getters = {
        cartList(state){
            // state.cartList[0] 如果没有返回,至少是个数组
            return state.cartList[0]|| [];
        },
    };
    
    export default {
        namespaced: true,
        state,
        mutations,
        actions,
        getters
    }
    

    现在仓库里面有了数据

组件获取数据展示数据

...mapGetters("shopcart", ["cartList"]), 组件开始获取数据

遍历用every


开始渲染数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i26xVFfG-1662259079861)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220808212414091.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-18SJZW75-1662259079862)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220808212440861.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EWbSh8pV-1662259079863)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220808212503712.png)]

UUID临时游客身份

在点击 加入购物车 的时候,告诉服务器你是谁

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gGm7EbdK-1662259079863)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220808192559148.png)]

utils :放一些常用的功能模块,比如正则,uuid

  1. 将游客身份用会话存储(sessionStorage)保存,放到detail仓库里

    uuid是一个随机的字符串,且每次执行不能发生变化,且持久存储,

    所以每次调用getUUID函数的时候,先从本地存储获取uuid,看会话存储是否有,

    如果有的话就返回会话存储里面的uuid,

    如果没有的话,就生成uuid

//      src/utils/uuid_token.js

import {v4 as uuidv4} from 'uuid'
// 要生成一个随机的字符串,且每次执行不能发生变化,游客身份持久存储
export const getUUID = ()=>{
    // 先从会话存储获取uuid,看一下本地存储是否有
    let uuid_token = sessionStorage.getItem('UUIDTOKEN');
    // 如果没有,我就生成UUID
    if(!uuid_token){
        uuid_token=uuidv4();
        // 会话存储 存储一次
        sessionStorage.setItem('UUIDTOKEN',uuid_token);
    }
    // 切记要有返回值!
    return uuid_token;
}

在detail仓库里面存储uuid

//     src/store/detail/index.js

// 封装游客身份模块uuid---生成一个随机的字符串(不能再变了)
import {getUUID} from '@/utils/uuid_token'
const state = {
    goodsInfo: {}, // 看api文档,result.data返回的是一个对象
    // 游客临时身份
    uuid_token:getUUID(),
};

现在游客身份在仓库里,我们要把数据带给服务器,可以利用请求头把数据带给服务器

找到请求拦截器,在请求拦截器捞到仓库里的数据

//   src/api/request.js

// 在当前模块引入store仓库
import store from '@/store'
.....
// 请求拦截器:在发请求之前,请求拦截器可以检测到,可以在请求发出去之前做一些事情
requests.interceptors.request.use((config) => {
    // config:配置对象,对象里面有一个属性很重要:headers请求头
    if (store.state.detail.uuid_token) {
        // 给请求头添加一个字段(userTempId):和后台老师商量好!
        config.headers.userTempId = store.state.detail.uuid_token
    }

    // 进度条开始动
    nprogress.start();
    return config;
})
image-20220808194942156

动态展示购物车

修改购物车产品的数量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K7aqRROw-1662259079864)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220809152304140.png)]

点击 + 或 - 或 修改input框里的数字,input框里发生变化

:这个时候向服务器发请求吗?

发请求,如果不发请求的话,服务器里的数据还是原来的,那么该页面的关于数量的数据和原来一样,

-----------所以我们每当修改的时候,就要发请求给服务器,然后再从服务器捞到数据,进行渲染页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WV58t3dV-1662259079865)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220809191528932.png)]

这个之前写过api(在将产品添加到购物车那里,detail详情页,也有仓库了)所以我们可以把数据存到detail仓库,就现在直接派发action就行了,然后再重新捞数据渲染

这里的skuNum是 现在状态的数字 与 起始状态的数字 的差值。比如:现在商品数量是5,我们要买12,这个skuNum是12-5 = 7

  1. 找到产品数量的结构位置

     
  2. - +
  3. 这三个节点 要派发同一个action,也就是说这三个节点调用同一个回调函数

    :但是如何判断这三个节点?

    通过传参。三个不同的参数,用形参接收,来区分这三个节点

  4. 要传三个参数

    第一个参数type 是用来区分它们三个节点

    第二个参数是disNum,他们的变化量,+号是1,-号是-1,input框暂定不是变化量,是修改后的值

    第三个参数是cart 当前他们点击的产品的信息cart,然后得知他们的id,因为要发请求需要skuID

      
  5. - +
  6. 先写 + 号 和 - 号

    加号:直接带给服务器变化的量

    减号:判断产品的当前数量是否大于1,大于1才能减,传递给服务器-1

    然后就是派发action发请求,发给服务器后再 捞数据 渲染页面

        // 购物车里 修改某一个产品的个数
        handler(type, disNum, cart) {
          //disNum 代表 现在状态的数字 与 起始状态的数字 的差值
          // 目前disNum 形参: + 号变化量(1),- 号 变化量 (-1),input 最终的量(并不是变化量)
          // 向服务器发请求,修改数量
          switch (type) {
            // 加号
            case "plus": {
              // 带给服务器变化的量
              disNum = 1;
              break;
            }
            // 减号
            case "mins": {
              // 判断产品的数量是否大于1,大于1才能减,传递给服务器-1
              if (cart.skuNum > 1) {
                disNum = -1;
              } else {
                // 产品的个数小于等于1,传递给服务器的个数为 0
                disNum = 0;
              }
              break;
            }
          }
            
          // 派发action 发请求
          try {
            // 代表的是修改购物车中产品数量修改成功
            await this.$store.dispatch("detail/addOrUpdateShopCart", {
              skuId: cart.skuId,
              skuNum: disNum,
            });
            // 再一次获取服务器的最新数据进行展示
            this.getData();
          } catch (error) {
            // 修改失败
            alert(error.message)
          }
        },
    
  7. 解决 input 框里面输入数字

    如果input框里面输入的不是数字,或者小于1,则带给服务器的数字是0

    如果输入的是小数,将你最终输入的取整,然后减去最初的数量,就是你要传的变化量disNum

      // input框
      case "change": {
              // 如果input框里面输入的不是数字,或者小于1,则带给服务器的数字是0
              if (isNaN(disNum) || disNum < 1) {
                disNum = 0;
              } else {
                // 如果输入的是小数,将你最终输入的取整,然后减去最初的数量,就是你要传的变化量disNum
                disNum = parseInt(disNum) - cart.skuNum;
              }
              break;
      }
    
  8. 对修改购物车产品的数量 进行节流操作

    当你刚到购物车页面的时候,快速点击 - 号,商品的数量会变成负数、

    这是因为 用户操作太频繁,请求服务器跟不上--------------所以我们用到【节流】,限制用户的操作

    //   原来写法
    
    async handler(type, disNum, cart) {
          //disNum 代表 现在状态的数字 与 起始状态的数字 的差值
          // 目前disNum 形参: + 号变化量(1),- 号 变化量 (-1),input 最终的量(并不是变化量)
          // 向服务器发请求,修改数量
          switch (type) {
            // 加号
            case "plus": {
              // 带给服务器变化的量
              disNum = 1;
              break;
            }
            // 减号
            case "mins": {
              // 判断产品的数量是否大于1,大于1才能减,传递给服务器-1
              if (cart.skuNum > 1) {
                disNum = -1;
              } else {
                // 产品的个数小于等于1,传递给服务器的个数为 0
                disNum = 0;
              }
              break;
            }
            // input框
            case "change": {
              // 如果input框里面输入的不是数字,或者小于1,则带给服务器的数字是0
              if (isNaN(disNum) || disNum < 1) {
                disNum = 0;
              } else {
                // 如果输入的是小数,将你最终输入的取整,然后减去最初的数量,就是你要传的变化量disNum
                disNum = parseInt(disNum) - cart.skuNum;
              }
              break;
            }
          }
          // 派发action 发请求
          try {
            // 代表的是修改购物车中产品数量修改成功
            await this.$store.dispatch("detail/addOrUpdateShopCart", {
              skuId: cart.skuId,
              skuNum: disNum,
            });
            // 再一次获取服务器的最新数据进行展示
            this.getData();
          } catch (error) {
            // 修改失败
            alert(error.message);
          }
        },
    
    1. 引入节流

      // 最好的引入方式:按需加载
      import throttle from "lodash/throttle";
      
      
    2. 整理代码

          // 购物车里 修改某一个产品的个数,使用【节流】
          handler: throttle(async function (type, disNum, cart) {
      		//  原来代码
          }, 500),
      

删除购物车产品

image-20220809211701626
  1. 写api接口

    //     src/api/index.js
    
    // 删除购物车商品数据    /api/cart/deleteCart/{skuId}   DELETE  带参数skuId
    export const reqDeleteCartById=(skuId)=>{
        return requests({url:`/cart/deleteCart/${skuId}`,method:'DELETE'})
    }  
    
  2. 写仓库vuex,去购物车的仓库里写

    这里就不用拿数据了,因为是删除数据!!!

    const actions = {
        // 删除购物车商品的数据
        async deleteCartListBySkuId({ commit }, skuId) {
            let result = await reqDeleteCartById(skuId);
            if (result.code == 200) {
                return 'ok'
            } else {
                return Promise.reject(new Error('删除购物车商品失败'))
            }
        }
    };
    

    点击 删除 的时候 派发action,需要传参,当前商品的skuId

      
  3. 删除
    移到收藏
  4. 删除购物车商品的操作

    如果删数据成功,则发请求显示新的数据,如果失败弹窗失败信息

        // 删除购物车商品的操作
        async deleteCartById(cart) {
          // 如果删数据成功,则发请求显示新的数据,如果失败弹窗失败信息
          try {
            await this.$store.dispatch(
              "shopcart/deleteCartListBySkuId",
              cart.skuId
            );
            //  再次发请求显示新的数据
            this.getData();
          } catch (error) {
            alert(error.message);
          }
        },
    

修改产品的勾选状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zxapznmq-1662259079865)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220810173640178.png)]

image-20220810173627839

每次修改完状态也是要向服务器发请求的

  1. 写api接口

    // 切换商品的选中状态    /api/cart/checkCart/{skuId}/{isChecked}  GET请求 带参数
    export const reqUpdateCheckedById = (skuId, isChecked) => {
        return requests({ url: `/cart/checkCart/${skuId}/${isChecked}`, method: 'GET' })
    }
    
  2. vuex----派发actions 与 仓库捞到数据 (不返回数据)

    多个参数的话,多个参数用{}对象包裹!!

    注意!不能只传个参数 cart ,因为isChecked不变的,它获取的是后台的数据,一直是1

    可以用event.target.checked获取当前元素的checked属性

       // src/pages/ShopCart/index.vue
    
     
  3. ..... // 修改购物车是否勾选状态 async updateChecked(cart, event) { try { let checked = event.target.checked ? "1" : "0"; // 注意,接口文档要的是string类型 await this.$store.dispatch("shopcart/updateCheckedById", { skuId: cart.skuId, isChecked: checked, }); this.getData(); } catch (error) { alert(err.message) } },
    const actions = {
        // 修改产品的勾选状态
        async updateCheckedById({ commit }, { skuId, isChecked }) {
            let result = await reqUpdateCheckedById(skuId, isChecked);
            if (result.code == 200) {
                return 'ok'
            } else {
                return Promise.reject(new Error('修改商品的勾选状态失败咯'))
            }
        }
    }
    

删除选中全部产品的操作

注意:没有一次删除很多产品的接口,但是有通过ID可以删除产品的接口【一次只能删一个】

------所以我们可以多调用几次接口

  1. 删除所选商品 绑定点击事件

            删除选中的商品
    
        // 删除所选中的全部商品
        // 这个回调函数我们没办法搜集到一些有用的数据
        deleteAllCheckedCart(){
          // 派发actions
          this.$store.dispatch('shopcart/deleteAllCheckedCart')
        },
    

    当点击 删除选中的商品,我们就要派发actions,执行shopcart里面的deleteAllCheckedCart回调函数来删除

  2. 我们想多调用几次删除商品的接口,这样就可以删除所选的全部商品了

    ​ actions里面的函数都有两个参数,第一个是context,它相当于一个小仓库,里面有 commit【提交mutations修改state】 getters【计算属性】 dispatch【派发actions】 state【当前仓库数据】

    调用删除商品的接口需要两个参数,要有dispatch可以派发actions才能调用,然后就是商品的ID

    所以我们的deleteAllCheckedCart 可以从context里面拿到两个参数,分别是dispatch和getters

    getters.cartList.cartInfoList; // 这就是购物车里的所有产品

    1. 我们可以用forEach来遍历购物车里面的所有商品,但是我们要删除的是勾选上的商品,所以可以用IF来进行判断,如果商品的isChecked为1,说明勾选上了,我们就让这个商品调用删除函数

    2. 我们要知道所选商品是否删除成功,可以用 Promise.all([p1,p2,p3])

      p1 | p2 | p3 每一个都是promise对象,如果有一个promise失败,都失败,如果都成功,返回成功

      让我们勾选上的商品都为promise,然后将每一次返回的promise添加到数组PromiseAll当中,最后Promise.all(PromiseAll)看你删除 勾选的全部商品成功还是失败

    const actions={
        .....
            // 删除勾选的全部产品
        deleteAllCheckedCart({ dispatch, getters }) {
            // 要拿到context里面的dispatth和getters,因为要派发action调用删除购物车的函数 ,以及需要数据
            // getters.cartList.cartInfoList; // 这就是购物车里的所有产品
            let PromiseAll = [];
            getters.cartList.cartInfoList.forEach(item => {
                // 购物车有多少产品,就调用多少 deleteCartListBySkuId 这个函数
                // !!但是我们要删除的是勾选上的商品
                let promise = item.isChecked == 1 ? dispatch('deleteCartListBySkuId', item.skuId) : '';
                // 将每一次返回的promise添加到数组当中
                PromiseAll.push(promise);
            });
            // Promise.all只要全部的商品都删除成功,返回结果就是成功
            return Promise.all(PromiseAll); // 看你删除勾选的全部商品成功还是失败
        }
    }
    
  3. 最后我们在用try...catch,如果成功,则再次发请求获取购物车列表,如果失败,报错

        // 删除所选中的全部商品
        // 这个回调函数我们没办法搜集到一些有用的数据
        async deleteAllCheckedCart() {
          try {
            // 派发actions
            await this.$store.dispatch("shopcart/deleteAllCheckedCart");
            // 再次发请求获取购物车列表
            this.getData();
          } catch (error) {
            alert(error.message)
          }
        },
      },
    

修改全部商品的勾选状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EOVCZLVM-1662259079866)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220811113304882.png)]

  • 我们现在解决了 当上面的勾选框全都勾选上了,下面的全选按钮全都勾选上

  • 但是没有解决 当下面全选按钮勾选上的时候,上面的也都要勾选上

    ​ 1. 修改产品的勾选状态 这个请求 一次只能勾选一个,而我们是要全部产品勾选上,所以我们可以多发几次请求。

    2. 当点击 【全选】的时候,派发一个actions,去调用一个函数【这个函数可以多次发请求修改产品的勾选状态】,这个函数 我们要执行【遍历上面所有产品,如果勾选框勾上了--不动,如果勾选框没勾上---发请求修改产品的勾选状态】
    
  1. 给【全选】绑定事件

    <div class="select-all">
            <input class="chooseAll" type="checkbox" :checked="isAllChecked" @change="updateAllCartChecked" />
            <span>全选span>
    div>
    
  2. 派发actions

    问:需要传参数吗

    答:需要,因为我们发请求的时候需要商品的ID和isChecked,而我们对商品的isChecked修改是根据 【全选】的checked来修改。如果全选的checked为1,那么商品的isChecked为1,否则就是0。所以我们需要拿到当前状态该【全选】的checked值

     // 修改全部产品的勾选状态
     updateAllCartChecked(event){
          // console.log(event.target.checked); // 返回的是布尔值 
          let isChecked = event.target.checked ? "1" : "0"; // 我们发请求需要的是布尔值
          // 派发actions 
          this.$store.dispatch('shopcart/updateAllCartIsChecked',isChecked)
     }
    
  3. vuex,多调用几次修改产品勾选状态的函数

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I9iG0G9l-1662259079866)(D:\桌面\前端学习\12-VUE\尚品汇-前台项目\project_SPH\尚品汇开发笔记.assets\image-20220811115204649.png)]

    我们拿state里面的数据state.cartList.cartInfoList 里面才是我们购物车里商品的数据

     // 修改全部商品的勾选状态
     updateAllCartIsChecked({ dispatch, getters }, isChecked) {
            let promiseAll = [];
            // 遍历购物车里面的所有商品
            getters.cartList.cartInfoList.forEach(item => {
                // 向修改产品的勾选状态发请求,带两个参数,第二个参数是【全选】的勾选状态
                // 目的:让购物车里面的商品勾选状态与全选一致
                let promise = dispatch('updateCheckedById', { skuId: item.skuId, isChecked: isChecked });
                promiseAll.push(promise); // 将每一次返回的promise添加到数组promiseAll当中
            });
            // 最终返回的结果  Promise.all只要全部的商品都修改成功,返回结果就是成功
            return Promise.all(promiseAll);
     },
    
  4. 最后我们用try...catch,如果成功,则再次发请求获取购物车列表,如果失败,报错

     // 修改全部商品的勾选状态
     updateAllCartIsChecked({ dispatch, getters }, isChecked) {
            let promiseAll = [];
            // 遍历购物车里面的所有商品
            getters.cartList.cartInfoList.forEach(item => {
                // 向修改产品的勾选状态发请求,带两个参数,第二个参数是【全选】的勾选状态
                // 目的:让购物车里面的商品勾选状态与全选一致
                let promise = dispatch('updateCheckedById', { skuId: item.skuId, isChecked: isChecked });
                promiseAll.push(promise); // 将每一次返回的promise添加到数组promiseAll当中
            });
            // 最终返回的结果  Promise.all只要全部的商品都修改成功,返回结果就是成功
            return Promise.all(promiseAll);
     },
    
  5. 解决小问题:当购物车里面商品没有的时候,全选框不可点击且不勾选上

    cartInfoList.length > 0当购物车商品数组长度>0才勾选上

    :disabled="cartInfoList == 0"当购物车商品数组长度=0,不能被点击

    全选

十、完成登录与注册页面

你可能感兴趣的:(Vue,vue.js,javascript,前端)