vue前台(八)

一, 对商品的数量输入框做限制,change事件,对输入框修改数据后,失去焦点后,对于负数控制

 <input autocomplete="off" class="itxt" v-model="skuNum" @change="$event.target.value*1 > 1? skuNum = $event.target.value*1 : skuNum = 1"/>

二,连接路由到去购物车结算页面

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

三,封装请求购物车列表数据函数

//请求购物车列表数据  /api/cart/cartList  get

export const reqShopCartList = () => Ajax.get('/cart/cartList')

四,在shopcart.js的 vuex的actions发送请求,然后在state存储响应数据

五,在ShopCart组件中dispatch到vuex中,但是此时,响应数据是空的,因为到购物车列表页面,此时是没有登录的,

需要搞一个临时身份信息标识uuid,后台存储后,可以识别身份信息

 

 

 
1.新建utils--userabout.js, 封装uuid的函数(用于配置工具函数),在本地localStorage存储一份,向外暴露该函数,安装uuid包,
import { v4 as uuidv4 } from 'uuid';

function getUserTempId(){
//这个是工具函数,它是专门用来生成或者得到用户的临时id的
  let userTempId = localStorage.getItem('USERTEMPID_KEY')
  //如果获取不到,证明用户之前没有生成过临时id
  if(!userTempId){
    userTempId = uuidv4()  // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
    localStorage.setItem('USERTEMPID_KEY',userTempId)
  }
  //如果存在就直接返回原来的,不存在返回的是新创建的
  return userTempId
}

export {
  getUserTempId
}
 
2,新建store--users.js, 引入uuid的函数,存储uuid必须用userTempId存储, 让临时id在vuex中存储,比存储在本地更快
 
import {} from '@/api'
import {getUserTempId} from '@/utils/userabout'
const state = {
  userTempId:getUserTempId()
}
const mutations = {
}

const actions = {
  
}

const getters = {
}

export default {
  state,
  mutations,
  actions,
  getters
}

 

3.在请求拦截器当中携带uuid,传送给后台,(从vuex中传递)引入import store from '@/store',
//请求拦截器内部一般不会处理错误的信息
service.interceptors.request.use(config => {
  //config是发送请求的配置对象,必须处理完返回这个配置对象
  //开启我们的进度条
  NProgress.start()

  //在请求头当中添加用户的临时id,让每个ajax请求都带着这个userTempId
  let userTempId = store.state.user.userTempId
  if(userTempId){
    config.headers.userTempId = userTempId
  }

  return config
});

 

注;此时未登录状态下,在ShopCart组件中dispatch到vuex中,响应是有数据的
 
4,shopcart组件从vuex中获取数据,从模板中填充数据
import { mapState } from 'vuex'
 computed:{
      ...mapState({
        shopCartList:state => state.shopcart.shopCartList
      }),
 
5,购物车动态数据计算属性数据的展示
模板填充数据
  <ul class="cart-list"  v-for="(shopcart, index) in shopcartList" :key="shopcart.id">
          <li class="cart-list-con1">
            <input type="checkbox" name="chk_list" :checked="shopcart.isChecked">
          </li>
          <li class="cart-list-con2">
            <img :src="shopcart.imgUrl">
            <div class="item-msg">{{shopcart.skuName}}</div>
          </li>
       
          <li class="cart-list-con4">
            <span class="price">{{shopcart.skuPrice}}</span>
          </li>
          <li class="cart-list-con5">
            <a href="javascript:void(0)" class="mins">-</a>
            <input autocomplete="off" type="text" :value="shopcart.skuNum" minnum="1" class="itxt">
            <a href="javascript:void(0)" class="plus">+</a>
          </li>
          <li class="cart-list-con6">
            <span class="sum">{{shopcart.skuPrice* shopcart.skuNum}}</span>
          </li>
          <li class="cart-list-con7">
            <a href="#none" class="sindelet">删除</a>
            <br>
            <a href="#none">移到收藏</a>
          </li>
        </ul>

 

 
 
5.1 , 计算购物车商品的总数
<div class="chosed">已选择
          <span>{{checkedNum}}</span>件商品</div>
        <div class="sumprice">

js代码

 checkedNum(){
        //统计的数组方法
        return this.shopCartList.reduce((pre,item,index)=>{
          //已经选中的商品
          if(item.isChecked){
            pre += item.skuNum
          }
          // console.log(pre)
          return pre
        },0)
      },

5.2, 计算购物车商品的总价

 <div class="sumprice">
          <em>总价(不含运费) :</em>
          <i class="summoney">{{allMoney}}</i>
        </div>

js代码

allMoney(){
        return this.shopCartList.reduce((pre,item,index) => {
          if(item.isChecked){
            pre += item.skuNum * item.skuPrice
          }
          return pre
        },0)
      },

 

 5.3,点击单选框,需要发送请求,更改单选框状态,响应体数据是空
   所有单选框选中,全选框自动选上,
  点击全选按钮框,所有的单选框都要选上
 
封装请求修改购物车选中状态函数
//请求修改购物车选中状态 /api/cart/checkCart/{skuID}/{isChecked}  get
export const reqUpdateIsChecked = (skuID,isChecked) => Ajax.get(`/cart/checkCart/${skuID}/${isChecked}`)

在vuex中发送该请求

 async updateIsChecked({commit},{skuId,isChecked}){
    const result = await reqUpdateIsChecked(skuId,isChecked)
    if(result.code === 200){
      return '修改选中状态成功'
    }else{
      return Promise.reject(new Error('修改选中状态失败'))
    }
  },

点击单选框,组件dispatch到vuex,发送请求,修改选择框的状态

  <li class="cart-list-con1">
            <input type="checkbox" name="chk_list" :checked="cart.isChecked" @click="updateOneIscheck(cart)">
          </li>
 //修改单个购物车选中状态信息,isChecked状态,1是选中,0是没选中
      async updateOneIscheck(cart){
        try {
          await this.$store.dispatch('updateIsChecked',{skuId:cart.skuId,isChecked:cart.isChecked === 1? 0 : 1})
          //重新发送请求,获取新的数据
          this.getShopCartList()
        } catch (error) {
          alert(error.message)
        }
      }

 

  1.所有单选框选中,全选框自动选上,get方法
  2.点击全选按钮框,所有的单选框都要选上, set方法
 
在组件shopCart点击全选按钮,改变选择框的状态

1.在组件shopCart改变选择框的状态,拿到改变后值,set(ischecked),dispatch到veux的actions的getReqUpdateIsAllChecked,
2.遍历每个选择框的状态,如果有选择框的状态和全选框的状态一致,就不用发送请修改状态的请求了
3.如果有选择框的状态和修改后的全选框的状态不一致,那么dispatch到getReqUpdateIsChecked,修改选择框的状态
4.初始化一个空数组promises, 如果每次dispatch到getReqUpdateIsChecked,那么往数组中添加这个promise
5.然后整体返回一个promsie return Promise.all(promises)
6.在组件中然后在发送请求,获取新的数据, this.getreqShopCartList()

在组件中计算全选按钮的状态

<div class="select-all">
        <input class="chooseAll" type="checkbox" v-model="isAllChecked">
        <span>全选</span>
      </div>

 

js代码
 isAllChecked:{
        get(){
          //返回布尔值,所有单选框选中后,全选框也会跟着选中
          return this.shopCartList.every((item,index) => item.isChecked === 1)
        },
        async set(val){
          //点击全选之后,会进入这个set逻辑
          try {
            const result = await this.$store.dispatch('updateAllIsChecked',val?1:0)
            // 重新发送请求,获取新的数据
            this.getShopCartList()
          } catch (error) {
            alert(error.message)
          }
        }
      }

在vuex中处理全选框选中后,单选框的状态变化

  //单选框选中发送请求
  async updateIsChecked({commit},{skuId,isChecked}){
    const result = await reqUpdateIsChecked(skuId,isChecked)
    if(result.code === 200){
      return '修改选中状态成功'
    }else{
      return Promise.reject(new Error('修改选中状态失败'))
    }
  },

  //选中全选框的逻辑
  updateAllIsChecked({commit,state,dispatch},isChecked){
    //定义数组存储每一项去发请求返回的promise对象
    let promises = []
    state.shopCartList.forEach(item => {
      //如果修改后全选按钮的状态和单选的状态一样,不用发送请求,更改状态
      if(item.isChecked === isChecked) return
      //如果不一致
      let promise = dispatch('updateIsChecked',{skuId:item.skuId,isChecked:isChecked})
      promises.push(promise)
    })
    
    //Promise.all 传递的参数必须是一个promise对象的数组,返回值也是一个promise 
    //返回的promise对象的成功和失败  看数组内部所有的promise对象是否成功,如果都成功,那么它就成功,如果有一个失败,那它就失败
    //成功的返回值promise的数据是一个数组 【每个成功的promise的数据】
    return Promise.all(promises)
  }

 

 
 
5.4,点击数量加减号,输入框输入数量,发送请求,输入的数量和后台数据库的商品数量做加法,才是修改后的数量
 
 
       <li class="cart-list-con5">
            <a href="javascript:void(0)" class="mins" @click="updateCartNum(cart,-1)">-</a>
            <input autocomplete="off" type="text" :value="cart.skuNum" minnum="1" class="itxt" @change="updateCartNum(cart,$event.target.value*1)">
            <a href="javascript:void(0)" class="plus" @click="updateCartNum(cart,1)">+</a>
          </li>

 

 js代码
  // 修改购物车某个商品的数量
      async updateCartNum(cart,changeNum){
        //changeNum是后面要发请求的参数,代表的是一个改变的数量
        if(cart.skuNum + changeNum < 1){
          changeNum = 1 - cart.skuNum
        }
        
        try {
          //请求修改购物车的商品数量   用原有的数量和改变的数量计算
          // await后是同步代码,必须他发送请求,修改数量后,才会立刻执行后面的请求
          await this.$store.dispatch('addorUpdateShopCart',{skuId:cart.skuId,skuNum:changeNum})
          //请求成功之后,重新获取购物车的列表信息,页面展示的就是最新的
          this.getShopCartList()
        } catch (error) {
          alert(error.message)
        }
      },

vuex发送的请求

const actions = {
  async addorUpdateShopCart({commit},{skuId,skuNum}){
    const result = await reqAddOrUpdateShopCart(skuId,skuNum)
    if(result.code === 200){
      return '添加购物车成功'
    }else{
      // return '添加购物车失败' 返回的还是成功的promise
      //返回的是失败的promise
      return Promise.reject(new Error('添加购物车失败'))
    }
  },

 

 
 
 
 
posted @ 2020-07-30 16:27  全情海洋  阅读(293)  评论(0编辑  收藏  举报