接day07–继续
//数据是服务器返回给仓库,仓库知道失败或者成功,但是数据是在详情页当中用的。就是调用vuex仓库中的addOrUpdateShopCart函数,调用这个函数有返回值,是一个Promise对象。成功或失败取决于返回值,有字符就是成功,失败可以输出error.message。所以在action里面,要对返回值进行判断
if (result.code == 200) {
return "ok"
} else {
//代表加入失败
return Promise.reject(new Error('fail'))
}
//仓库中返回成功或失败的标记,详情页当中要用的try-catch。
组件中,也要等待返回的结果,成功或者失败
async addShopCar() {
try {
//发请求--成功
await this.$store.dispatch("detail/addOrUpdateShopCart", {
skuId: this.$route.params.skuid,
skuNum: this.skuNum,
});
//服务器存储成功---进行路由跳转传递参数
} catch (error) {
//失败---提示用户
alert(error.message);
}
},
导入加入购物车成功的静态路由组件—注册路由
import AddCartSuccess from '@/pages/AddCartSuccess'
{
path: '/addcartsuccess',
component: AddCartSuccess,
meta: { show: true }
},
接下来进行路由跳转
详情页中的购买信息在购物车页面也要用—路由跳转的时候参数带过去—购物车路由组件捞数据
传参用了两个手段 query
和会话存储(单页面没必要本地存储)
//1 详情页路由组件中
//成功---进行路由跳转
//还需要将产品信息带给下一级的路由组件---把detail中的数据给addcart传过去
//第一种 query传参---不推荐,地址栏会很恶心---传点简单的可以
this.$router.push({ name: "addcartsuccess" ,query:{skuInfo:this.skuInfo,skuNum:this.skuNum}});
//第二种
//简单数据skuNum,通过query形式给路由组件传递;复杂信息skuInfo,通过会话存储(此页面不需要持久化)---不能存对象---json转换字符串
//本地存储|会话存储:一般存字符串,不能存对象---json
sessionStorage.setItem("SKUINFO", JSON.stringify(this.skuInfo));--复杂的
this.$router.push({ name: "addcartsuccess" ,query:{skuNum:this.skuNum}});---简单的
//2 购物车路由组件中
computed: {
skuInfo() {
return JSON.parse(sessionStorage.getItem("SKUINFO"));
},
},
//3 购物车路由组件中展示
<img :src="skuInfo.skuDefaultImg" />
{{ skuInfo.skuName }}
{{ skuInfo.skuDesc }} 数量:{{ $route.query.skuNum }}
浏览器存储功能:HTML5
新增的:本地存储,会话存储(注意区别)
提前导入shopcart
路由组件,并在routes
中注册好shopcart
路由
<router-link :to="`/detail/${skuInfo.id}`" class="sui-btn btn-xlarge">查看商品详情router-link>
<router-link to="/shopcart">去购物车结算 > router-link>
1 静态组件处理—修改样式
2 向服务器发请求,获取数据,操作vuex
三连环,组件获取数据展示数据
//1
export const reqShopCartList = ()=>request({url:'/cart/cartList',method:'get'});
//2
//获取购物车数据的方法
async getShopCart({ commit }) {
let result = await reqShopCartList();
//如果成功
if (result.code == 200) {
commit('GETSHOPCART', result.data);
}
}
//3 购物车路由组件中
mounted() {
//获取购物车的数据
this.getShopCartData();
},
给服务器加入数据的时候,要告诉服务器你是谁,不然返回的是空数据
提交购物车的时候,给用户加一个身份—token
/uuid
当时在detail
仓库只带了id
和num
uuid要怎么带给服务器呢—通过请求头
一般新建文件
utils
存放功能—token
和正则
等
utils
中的功能将来要在detail
中使用
//1 detail仓库中---封装游客身份模块uuid--->生成一个随机字符串(不能在变了)
import {getUUID} from '@/utils/uuid_token';
//3 detail中--现在这个id在仓库里面了--我们需要带给服务器----->4
const state = {
//游客临时身份---调用utils中的暴露函数getUUID()
//这里如果直接调用uuid会导致每次id都不一样
uuid_token:getUUID()
};
//2 utils-->uuid_token.js
import { v4 as uuidv4 } from 'uuid';
//要生成一个随机字符串,且每次执行不能发生变化,游客身份持久存储
export const getUUID = ()=>{
//先从本地存储获取uuid(看一下本地存储里面是否有)
let uuid_token = localStorage.getItem('UUIDTOKEN');
//如果没有
if(!uuid_token){
//我生成游客临时身份
uuid_token = uuidv4();
//本地存储存储一次
localStorage.setItem('UUIDTOKEN',uuid_token);
}
//切记有返回值,没有返回值undefined
return uuid_token;
}
//4 detail仓库发请求只能带两个参数id和num,谁还可以带参数呢----请求头
//在api--->ajax.js中引入store
//在当前模块中引入store
import store from '@/store';
requests.interceptors.request.use((config) => {
if(store.state.detail.uuid_token){
//请求头添加一个字段(userTempId):和后台老师商量好了
config.headers.userTempId = store.state.detail.uuid_token;
}
});
仓库中已经可以获取到游客购物车的信息,接下来就是—仓库存储—组件捞–动态展示
获取的信息中,数据格式比较复杂—getters
//购物车仓库中可以捞到数据了---三连环
//1 actions中---获取购物车列表数据
actions: {
//通过API里面的接口函数调用,向服务器发请求,获取服务器的数据
async getShopCart(context) {
const result = await reqShopCartList();
//成功返回的话我们要修改仓库中的数据了
if (result.code == 200) {
context.commit('GETSHOPCART', result.data)
}
},
},
//2 mutations中
mutations: {
GETSHOPCART(state, cartList) {
state.cartList = cartList
},
},
//3
const state = {
cartList: [],
};
//4 这个数据不是我们最终想要的数据---先简化一下getters----cartList这个是我们想要的
getters: {
cartList(state) {
return state.cartList[0] || {}
},
}
//5 购物车路由组件捞数据
import { mapGetters } from "vuex";
computed: {
...mapGetters("shopcart", ["cartList"]),
//再简化一下数据,这个是我们想要的购物车数据
cartInfoList() {
return this.cartList.cartInfoList || [];
},
},
// v-for="cart in cartInfoList" :key="cart.id"
<ul class="cart-list" v-for="cart in cartInfoList" :key="cart.id">......ul>
// :checked="cart.isChecked == 1"
<input type="checkbox"name="chk_list" :checked="cart.isChecked == 1"/>
//一步步换数据展示出来
//小计要自己算一下---同理总计也要自己算一下
<span class="sum">{{ cart.skuNum * cart.skuPrice }}span>
//同理总计也要自己算一下
totalPrice() {
let sum = 0;
this.cartInfoList.forEach((item) => {
sum += item.skuNum * item.skuPrice;
});
return sum;
},
//全选打勾与上面打勾的联系
isAllCheck() {
//遍历数组里面元素,只要全部元素isChecked属性都为1===>真 true
//只要有一个不是1======>假false
return this.cartInfoList.every((item) => item.isChecked == 1);
},
购物车中修改数量
这个之前在详情页中做过,现在接口有了,仓库有了,派发action就好了
//@click="handler('minus', -1, cart)"
<a
href="javascript:void(0)"
class="mins"
@click="handler('minus', -1, cart)"
>-a
>
//@change="handler('change', $event.target.value * 1, cart)"-----:value="cart.skuNum"
<input
autocomplete="off"
type="text"
minnum="1"
class="itxt"
:value="cart.skuNum"
@change="handler('change', $event.target.value * 1, cart)"
/>
//@click="handler('add', 1, cart)"
<a
href="javascript:void(0)"
class="plus"
@click="handler('add', 1, cart)"
>+a
>
//修改某一个产品的个数[节流]
handler: throttle(async function(type, disNum, cart) {
//type:为了区分这三个元素
//disNum形参:+ 变化量(1) -变化量(-1) input最终的个数(并不是变化量)
//cart:哪一个产品【身上有id】
//向服务器发请求,修改数量
switch (type) {
//加号
case "add":
disNum = 1;
break;
case "minus":
//判断产品的个数大于1,才可以传递给服务器-1
//如果出现产品的个数小于等于1,传递给服务器个数0(原封不动)
disNum = cart.skuNum > 1 ? -1 : 0;
break;
case "change":
// //用户输入进来的最终量,如果非法的(带有汉字|出现负数),带给服务器数字零
if (isNaN(disNum) || disNum < 1) {
disNum = 0;
} else {
//属于正常情况(小数:取整),带给服务器变化的量 用户输入进来的 - 产品的起始个数
disNum = parseInt(disNum) - cart.skuNum;
}
// disNum = (isNaN(disNum)||disNum<1)?0:parseInt(disNum) - cart.skuNum;
break;
}
//派发action
try {
//代表的是修改成功
await this.$store.dispatch("detail/addOrUpdateShopCart", {
skuId: cart.skuId,
skuNum: disNum,
});
//再一次获取服务器最新的数据进行展示
this.getData();
} catch (error) {}
}, 500),