焦作網(wǎng)站建設兼職網(wǎng)絡推廣公司哪家做得好
文章目錄
- 29.加入購物車操作(難點)
- 29.1加入購物車按鈕
- 29.2addCartSuce
- 29.3購物車
- 29.3.1 向服務器發(fā)送ajax請求,獲取購物車數(shù)據(jù)
- 29.3.2UUID臨時游客身份
- 29.3.3動態(tài)展示購物車
- 29.4修改購物車產(chǎn)品的數(shù)量(需要發(fā)請求:參數(shù)理解)
- 29.5刪除某一產(chǎn)品
- 29.6修改產(chǎn)品狀態(tài)
- 29.7刪除全部選中的商品
- 29.8全選操作
- 本人其他相關(guān)文章鏈接
29.加入購物車操作(難點)
重難點說明
-
用戶臨時ID的處理
-
購物車數(shù)據(jù)的管理(復雜)
-
不使用v-model監(jiān)控用戶輸入
-
async / await / Promise.all() 的使用
思路:
-
加入購物車按鈕
-
路由跳轉(zhuǎn)之前發(fā)請求
-
成功路由跳轉(zhuǎn)與參數(shù)傳遞
-
失敗提示失敗信息
-
-
addCartSuce
- 查看詳情
- 查看購物車
-
購物車
- 購物車靜態(tài)組件-需要修改樣式結(jié)構(gòu)(刪除第三項并調(diào)整css讓各個項目對齊,比例為:15 35 10 17 10 13)
- 向服務器發(fā)送ajax請求,獲取購物車數(shù)據(jù)
- UUID臨時游客身份
- 動態(tài)展示購物車
-
修改購物車產(chǎn)品的數(shù)量(需要發(fā)請求:參數(shù)理解)
-
刪除某一產(chǎn)品
-
修改產(chǎn)品狀態(tài)
-
刪除全部選中的商品
-
全選操作
29.1加入購物車按鈕
加入購物車按鈕
-
路由跳轉(zhuǎn)之前發(fā)請求
-
成功路由跳轉(zhuǎn)與參數(shù)傳遞
-
失敗提示失敗信息
修改代碼:
src/pages/Detail/index.vue
<a href="javascript:" @click="addOrUpdateShopCar">加入購物車</a>methods: {//加入購物車async addOrUpdateShopCar() {//1:在點擊加入購物車這個按鈕的時候,做的第一件事情,將參數(shù)帶給服務器(發(fā)請求),通知服務器加入購車的產(chǎn)品是誰//this.$store.dispatch('addOrUpdateShopCart'),說白了,它是在調(diào)用vuex倉庫中的這個addOrUpdateShopCart函數(shù)。//2:你需要知道這次請求成功還是失敗,如果成功進行路由跳轉(zhuǎn),如果失敗,需要給用戶提示try {//成功await this.$store.dispatch("addOrUpdateShopCar", {skuId: this.$route.params.skuId, skuNum: this.skuNum});//3:進行路由跳轉(zhuǎn)//4:在路由跳轉(zhuǎn)的時候還需要將產(chǎn)品的信息帶給下一級的路由組件//一些簡單的數(shù)據(jù)skuNum,通過query形式給路由組件傳遞過去//產(chǎn)品信息的數(shù)據(jù)【比較復雜:skuInfo】,通過會話存儲(不持久化,會話結(jié)束數(shù)據(jù)在消失)//本地存儲|會話存儲,一般存儲的是字符串sessionStorage.setItem("SKUINFO", JSON.stringify(this.skuInfo))this.$router.push({name: "addCartSuccess", query:{skuNum: this.skuNum}})} catch (error) {//失敗alert(error.message);}}
}
src/api/index.js
//將產(chǎn)品添加到購物車中(獲取更新某一個產(chǎn)品的個數(shù))
// /api/cart/addToCart/{ skuId }/{ skuNum } POST
export const addOrUpdateShopCar = (skuId, skuNum)=>requests({url:`/cart/addToCart/${skuId}/${skuNum}`, method:"post"});
src/store/detail/index.js
import {getGoodsInfo, addOrUpdateShopCar} from "@/api";const actions = {//加入購物車的||修改某一個產(chǎn)品的個數(shù),注意一定要用解構(gòu)方法解構(gòu)形參對象,不能寫成接收兩個形參形式,那樣會報錯接口調(diào)不通async addOrUpdateShopCar(context, {skuId, skuNum}) {//發(fā)請求:前端帶一些參數(shù)給服務器【需要存儲這些數(shù)據(jù)】,存儲成功了,沒有給返回數(shù)據(jù)//不需要在三連環(huán)(倉庫存儲數(shù)據(jù)了)//注意:async函數(shù)執(zhí)行返回的結(jié)果一定是一個promise【要么成功,要么失敗】let response = await addOrUpdateShopCar(skuId, skuNum);if (response.code == 200) {//返回的是成功的標記return "OK";} else {//返回的是失敗的標記return Promise.reject(new Error("fail"))}},
}
注意點1:
問題:加入購物車路由跳轉(zhuǎn)跟普通的路由跳轉(zhuǎn)不一樣,不一樣在哪里?
答案:因為加入購物車功能得先調(diào)接口保存加入購物車的數(shù)據(jù),然后再跳轉(zhuǎn)路由。而普通的路由跳轉(zhuǎn)直接跳轉(zhuǎn)并傳參就行。
注意點2:
問題:點擊購物車函數(shù)派發(fā)定義在詳情組件中,但是加入購物車接口調(diào)用在倉庫中,如何獲取調(diào)用函數(shù)的結(jié)果呢?
答案:第一種方案在vuex的state中保存結(jié)果,第二種方案在詳情組件中采用async+await修飾派發(fā)方法獲取調(diào)用成功失敗結(jié)果。
注意點3:
問題:如下代碼vuex中執(zhí)行ajax調(diào)用接口返回失敗,為啥?
src/api/index.js
//將產(chǎn)品添加到購物車中(獲取更新某一個產(chǎn)品的個數(shù))
// /api/cart/addToCart/{ skuId }/{ skuNum } POST
export const addOrUpdateShopCar = (skuId, skuNum)=>requests({url:`/cart/addToCart/${skuId}/${skuNum}`, method:"post"});
src/store/detail/index.js
async addOrUpdateShopCar(context, skuId, skuNum) {let response = await addOrUpdateShopCar(skuId, skuNum);console.log("******response:", response) }
報錯如下:
答案:vuex中action定義的函數(shù)接收形參書寫個數(shù)不對。
如果是一個參數(shù)可以寫成:addOrUpdateShopCar(context, skuId)
但如果是傳入多個參數(shù)則不能這樣寫:這是錯誤寫法:addOrUpdateShopCar(context, skuId, skuNum)
正確寫法是派發(fā)時傳入一個對象通過解構(gòu)方式獲取屬性值,正確寫法:addOrUpdateShopCar(context, {skuId, skuNum})
注意點4:
問題:理解異步函數(shù)async和await的用法?
答案:
- async 函數(shù)
1)函數(shù)的返回值為Promise對象
2)Promise對象的結(jié)果由async函數(shù)執(zhí)行的返回值決定 - await 表達式
1)await右側(cè)的表達式一般為promise對象, 但也可以是其它的值
2)如果表達式是promise對象,await就忙起來了,它會阻塞函數(shù)后面的代碼,等著Promise對象resolve,然后得到resolve的值,
作為await表達式的運算結(jié)果。
3)如果表達式是其它值, 直接將此值作為await的返回值 async
和await
基于promise的。使用async的函數(shù)將會始終返回一個 promise 對象。這一點很重要,要記住,可能是你遇到容易犯錯的地方。- 在使用
await
的時候我們只是暫停了函數(shù),而非整段代碼。 - async和await是
非阻塞的
- 仍然可以使用
Promise
,例如Promise.all()
. - 注意
1)await
必須寫在async
函數(shù)中, 但async函數(shù)中可以沒有await
2)如果await的promise失敗了, 就會拋出異常, 需要通過try…catch
來捕獲處理
29.2addCartSuce
重難點說明:區(qū)別使用sessionStorage與localStorage
addCartSuce
- 查看詳情
- 查看購物車
效果如圖
修改代碼:
拷貝src/pages/AddCartSuccess文件夾
src/router/routes.js
import AddCartSuccess from '@/pages/AddCartSuccess'
import ShopCart from '@/pages/ShopCart'
{name: 'addCartSuccess',path: '/addCartSuccess',component: AddCartSuccess,meta:{"isShow": true} //自定義元數(shù)據(jù)屬性,判斷Footer組件在底部是否顯示
},
{name: 'shopCart',path: '/shopCart',component: ShopCart,meta:{"isShow": true} //自定義元數(shù)據(jù)屬性,判斷Footer組件在底部是否顯示
},
src/pages/AddCartSuccess/index.vue
<img :src="skuInfo.skuDefaultImg">
<p class="title">{{skuInfo.skuName}}</p>
<p class="attr">{{skuInfo.skuDesc}} 數(shù)量:{{$route.query.skuNum}}</p>
<router-link class="sui-btn btn-xlarge" :to="`/detail/${skuInfo.id}`">查看商品詳情</router-link>
<router-link to="/shopCart">去購物車結(jié)算</router-link>computed: {skuInfo() {return JSON.parse(sessionStorage.getItem("SKUINFO"))}
}
注意點1:
問題:點擊加入購物車按鈕后跳轉(zhuǎn)路由需要傳參購物詳情參數(shù),采用哪種方式?query?params?
答案:其實都可以,但是最優(yōu)雅的還是采用query方式,具體效果看如下:
- 首先是采用params方式,地址欄顯示的是地址字符串,但組件中控制臺打印居然也能正確解析,說明能獲取到參數(shù),但是URL看起來一大長串東西還是不優(yōu)雅,萬一后續(xù)URL一頓追加參數(shù),豈不是越來越長根本不優(yōu)雅。
- 而采用query方式,地址欄很清爽,所以推薦采用這種方式傳參。
注意點2:
問題:參數(shù)傳遞采用本地存儲好還是會話存儲好?
答案:推薦采用會話存儲,localStorage本地存儲會在硬盤保留一份需手動清除,而sessionStorage會話存儲隨著瀏覽器窗口關(guān)閉就清楚了,使用方便。
注意點3:
問題:無論是本地存儲還是會話存儲,可以存對象嗎?
答案:不能,只能存json字符串,直接存對象會無法解析。
- 存儲存對象效果,這東西無法解析:
29.3購物車
購物車
- 購物車靜態(tài)組件-需要修改樣式結(jié)構(gòu)(刪除第三項并調(diào)整css讓各個項目對齊,比例為:15 35 10 17 10 13)
- 向服務器發(fā)送ajax請求,獲取購物車數(shù)據(jù)
- UUID臨時游客身份
- 動態(tài)展示購物車
29.3.1 向服務器發(fā)送ajax請求,獲取購物車數(shù)據(jù)
修改代碼:
src/api/index.js
//獲取購物車列表數(shù)據(jù)接口
//URL:/api/cart/cartList method:get
export const reqCartList = ()=>requests({url:'/cart/cartList ',method:'get'});
src/store/index.js
import shopCar from "@/store/shopCar"modules:{...shopCar}
src/store/shopCar/index.js
import {reqCartList} from "@/api";//shopCar模塊的小倉庫
//actions代表一系列動作,可以書寫自己的業(yè)務邏輯,也可以處理異步
const actions = {async reqCartList({commit}) {let response = await reqCartList();if (response.code == 200) {commit("REQ_CART_LIST", response.data)}},}
//mutations代表維護,操作維護的是state中的數(shù)據(jù),且state中數(shù)據(jù)只能在mutations中處理
const mutations = {REQ_CART_LIST(state, carList) {state.carList = carList},
}
//state代表倉庫中的數(shù)據(jù)
const state = {//購物車列表carList: [],
}
//計算屬性
//項目當中g(shù)etters主要的作用是:簡化倉庫中的數(shù)據(jù)(簡化數(shù)據(jù)而生)
//可以把我們將來在組件當中需要用的數(shù)據(jù)簡化一下【將來組件在獲取數(shù)據(jù)的時候就方便了】
const getters = {carList(state) {return state.carList[0] || {};}
}//創(chuàng)建并暴露store
export default {actions,mutations,state,getters
}
src/pages/ShopCart/index.vue
methods: {getData() {this.$store.dispatch('reqCartList')},},
mounted() {this.getData()
}
注意點1:如圖,這一列多余,刪除第三項并調(diào)整css讓各個項目對齊,比例為:15 35 10 17 10 13
注意點2:
問題:向服務器發(fā)送查詢購物車ajax請求,獲取購物車數(shù)據(jù),為啥返回數(shù)據(jù)是空呢?
答案:因為你得帶UUID的東西,后端不知道你誰,也就不知道把那條數(shù)據(jù)返回給你了。
29.3.2UUID臨時游客身份
安裝命令:cnpm install --save uuid
修改代碼:
src/utils/uuid_token.js
import { v4 as uuidv4 } from 'uuid';
//要生成一個隨機字符串,且每次執(zhí)行不能發(fā)生變化,游客身份持久存儲
export const getUUID = ()=>{//先從本地存儲獲取uuid(看一下本地存儲里面是否有)let uuid_token = localStorage.getItem('UUIDTOKEN');//如果沒有if(!uuid_token){//我生成游客臨時身份uuid_token = uuidv4();//本地存儲存儲一次localStorage.setItem('UUIDTOKEN',uuid_token);}//切記有返回值,沒有返回值undefinedreturn uuid_token;
}
src/api/axios.js
//在當前模塊中引入store
import store from '@/store';
if(store.state.detail.uuid_token){//請求頭添加一個字段(userTempId):和后臺老師商量好了config.headers.userTempId = store.state.detail.uuid_token;
}
src/store/detail/index.js
const state = {//游客臨時身份uuid_token: getUUID()
}
注意點1:
問題:假設現(xiàn)在我有UUID了,那如何傳過去呢?接口已經(jīng)定義好了只有2個參數(shù),UUID咋傳過去?
答案:可以放在請求頭header中傳遞過去。
注意點2:
問題:我如何使用UUID第三方插件呢?
答案:登錄npm官網(wǎng)https://www.npmjs.com/package/uuid搜索uuid,下方就是使用方式。
注意點3:切記UUID不能在vuex中生成,因為vuex是每次觸發(fā)就會隨機生成,會變動這是不行的,正常應該是一次生成有效期內(nèi)不改變。所以這個uuidv4()不能放在vuex中,最好放在src目錄下新建一個文件夾utils,這個文件夾里面經(jīng)常放一些常用的功能模塊,比如正則、臨時身份UUID等等。
注意點4:切記src/utils/uuid_token.js下封裝的uuid方法一定要有返回值,否則返回值是underfine無效的。
注意點5:
問題:在src/api/axios.js中現(xiàn)在需要給請求頭header添加uuid,但是uuid在vuex倉庫中,如何獲取呢?
答案:在src/api/axios.js中引入import store from ‘@/store’;,通過store 對象可以獲取倉庫中的state屬性。
29.3.3動態(tài)展示購物車
修改代碼:
src/pages/ShopCart/index.vue
<ul class="cart-list" v-for="(car, index) in cartInfoList" :key="car.id">
<input type="checkbox" name="chk_list" :checked="car.isChecked == 1">
<div class="item-msg">{{car.skuName}}</div>
<span class="price">{{car.skuPrice}}.00</span>
<input autocomplete="off" type="text" :value="car.skuNum" minnum="1" class="itxt">
<span class="sum">{{car.skuNum * car.skuPrice}}</span>
<i class="summoney">{{carTotalPrice}}</i>import {mapGetters} from "vuex";
data() {return {totalPrice: 0}},computed: {...mapGetters(["carList"]),//購物車數(shù)據(jù)cartInfoList() {return this.carList.cartInfoList || []},//計算購買產(chǎn)品的總價carTotalPrice() {this.cartInfoList.forEach(item => {this.totalPrice += item.skuNum * item.skuPrice;})return this.totalPrice;},//判斷底部復選框是否勾選【全部產(chǎn)品都選中,采勾選】isAllChecked() {//遍歷數(shù)組里面原理,只要全部元素isChecked屬性都為1===>真 true//只要有一個不是1======>假falsereturn this.cartInfoList.every(item=> item.isChecked == 1)}}
注意點1:
問題:查詢購物車信息的接口方法放在哪里?是放在“去購物車結(jié)算”按鈕還是放在“購物車”頁面加載完畢中定義?
答案:放在“購物車”頁面加載完畢中定義,只要購物車頁面一初始化,甭管哪個入口跳轉(zhuǎn)進來的都能進行批量查詢購物車數(shù)據(jù)并動態(tài)展示。
注意點2:購物車左下角的全選按鈕判斷是否勾選,推薦適用every而不是foreach方法
isAllChecked() {//遍歷數(shù)組里面原理,只要全部元素isChecked屬性都為1===>真 true//只要有一個不是1======>假falsereturn this.cartInfoList.every(item=> item.isChecked == 1)
}
29.4修改購物車產(chǎn)品的數(shù)量(需要發(fā)請求:參數(shù)理解)
修改代碼:
src/pages/ShopCart/index.vue
<li class="cart-list-con5"><a href="javascript:void(0)" class="mins" @click="handle('minus', -1, car)">-</a><input autocomplete="off" type="text" :value="car.skuNum" minnum="1" class="itxt" @change="handle('change', $event.target.value * 1, car)"><a href="javascript:void(0)" class="plus" @click="handle('add', 1, car)">+</a>
</li>//引入lodash:是把lodash全部封裝好的函數(shù)全都引入進來了
//按需引入:只是引入節(jié)流函數(shù),其他的函數(shù)沒有引入(模塊),這樣做的好處是,當你打包項目的時候體積會小一些
import throttle from "lodash/throttle";
methods: {//修改某一個產(chǎn)品的個數(shù)[節(jié)流]handle: throttle(async function(flag, disNum, car) {//type:為了區(qū)分這三個元素//disNum形參:+ 變化量(1) -變化量(-1) input最終的個數(shù)(并不是變化量)//cart:哪一個產(chǎn)品【身上有id】//向服務器發(fā)請求,修改數(shù)量switch (flag) {case "add"://加號disNum = 1;break;case "minus"://判斷產(chǎn)品的個數(shù)大于1,才可以傳遞給服務器-1//如果出現(xiàn)產(chǎn)品的個數(shù)小于等于1,傳遞給服務器個數(shù)0(原封不動)disNum = car.skuNum > 1 ? -1 : 0;break;case "change":/*用戶輸入進來的最終量,如果非法的(帶有漢字|出現(xiàn)負數(shù)),帶給服務器數(shù)字零* 問題:為啥是disNum < 1,而不是disNum <= 1* 答案:哪怕輸入1也會走else里面的代碼,不影響功能,所以無需加“=”等于號*/if (isNaN(disNum) || disNum < 1) {disNum = 0;} else {//屬于正常情況(小數(shù):取證),帶給服務器變化的量 用戶輸入進來的 - 產(chǎn)品的起始個數(shù)disNum = parseInt(disNum) - car.skuNum;}break;}try {//派發(fā)actionawait this.$store.dispatch('addOrUpdateShopCar', {skuId: car.skuId, skuNum: disNum})//再一次獲取服務器最新的數(shù)據(jù)進行展示this.getData();} catch (error) {//失敗alert(error.message);}}, 500),
}
注意點1:如圖,購物車中的【+、-、輸入值】都應該觸發(fā)修改購物車接口,且三個函數(shù)是同一個函數(shù)
注意點2:
問題:如何區(qū)分是點擊了加號、減號、還是輸入值呢?
答案:通過傳參字符串flag標識名稱進行區(qū)分。
注意點3:
問題:實際觸發(fā)修改購物車接口的傳值要注意。
答案:點擊“+”號應傳值(1),點擊“-”號應傳值(-1),點擊輸入值應傳值(輸入值-原始值)。
注意點4:輸入框中事件一定要寫成@change,而不是@click,否則效果不對。
注意點5:
問題:對于“minus”情況,為啥是disNum < 1,而不是disNum <= 1
答案:哪怕輸入1也會走else里面的代碼,不影響功能,所以無需加“=”等于號
注意點6:點擊減號“-”要加判斷,不能讓值小于1。
case "minus"://判斷產(chǎn)品的個數(shù)大于1,才可以傳遞給服務器-1//如果出現(xiàn)產(chǎn)品的個數(shù)小于等于1,傳遞給服務器個數(shù)0(原封不動)disNum = car.skuNum > 1 ? -1 : 0;break;
注意點7:對于“change”情況,也要加判斷
case "change":/*用戶輸入進來的最終量,如果非法的(帶有漢字|出現(xiàn)負數(shù)),帶給服務器數(shù)字零* 問題:為啥是disNum < 1,而不是disNum <= 1* 答案:哪怕輸入1也會走else里面的代碼,不影響功能,所以無需加“=”等于號*/ if (isNaN(disNum) || disNum < 1) {disNum = 0;} else {//屬于正常情況(小數(shù):取證),帶給服務器變化的量 用戶輸入進來的 - 產(chǎn)品的起始個數(shù)disNum = parseInt(disNum) - car.skuNum;}break;
注意點8:
問題:連續(xù)點擊,居然能出現(xiàn)負數(shù),而慢慢點擊就不會出問題,為什么?
答案:因為沒有加“節(jié)流”效果,由于點擊過快就會出現(xiàn)這種錯誤現(xiàn)象。
舊代碼:
//修改某一個產(chǎn)品的個數(shù)[節(jié)流]async handle(flag, disNum, car) {//type:為了區(qū)分這三個元素//disNum形參:+ 變化量(1) -變化量(-1) input最終的個數(shù)(并不是變化量)//cart:哪一個產(chǎn)品【身上有id】//向服務器發(fā)請求,修改數(shù)量switch (flag) {case "add"://加號disNum = 1;break;case "minus"://判斷產(chǎn)品的個數(shù)大于1,才可以傳遞給服務器-1//如果出現(xiàn)產(chǎn)品的個數(shù)小于等于1,傳遞給服務器個數(shù)0(原封不動)disNum = car.skuNum > 1 ? -1 : 0;break;case "change":/*用戶輸入進來的最終量,如果非法的(帶有漢字|出現(xiàn)負數(shù)),帶給服務器數(shù)字零* 問題:為啥是disNum < 1,而不是disNum <= 1* 答案:哪怕輸入1也會走else里面的代碼,不影響功能,所以無需加“=”等于號*/if (isNaN(disNum) || disNum < 1) {disNum = 0;} else {//屬于正常情況(小數(shù):取證),帶給服務器變化的量 用戶輸入進來的 - 產(chǎn)品的起始個數(shù)disNum = parseInt(disNum) - car.skuNum;}break;}try {//派發(fā)actionawait this.$store.dispatch('addOrUpdateShopCar', {skuId: car.skuId, skuNum: disNum})//再一次獲取服務器最新的數(shù)據(jù)進行展示this.getData();} catch (error) {//失敗alert(error.message);}},
修改后代碼
//引入lodash:是把lodash全部封裝好的函數(shù)全都引入進來了
//按需引入:只是引入節(jié)流函數(shù),其他的函數(shù)沒有引入(模塊),這樣做的好處是,當你打包項目的時候體積會小一些
import throttle from "lodash/throttle";//修改某一個產(chǎn)品的個數(shù)[節(jié)流]handle: throttle(async function(flag, disNum, car) {//type:為了區(qū)分這三個元素//disNum形參:+ 變化量(1) -變化量(-1) input最終的個數(shù)(并不是變化量)//cart:哪一個產(chǎn)品【身上有id】//向服務器發(fā)請求,修改數(shù)量switch (flag) {case "add"://加號disNum = 1;break;case "minus"://判斷產(chǎn)品的個數(shù)大于1,才可以傳遞給服務器-1//如果出現(xiàn)產(chǎn)品的個數(shù)小于等于1,傳遞給服務器個數(shù)0(原封不動)disNum = car.skuNum > 1 ? -1 : 0;break;case "change":/*用戶輸入進來的最終量,如果非法的(帶有漢字|出現(xiàn)負數(shù)),帶給服務器數(shù)字零* 問題:為啥是disNum < 1,而不是disNum <= 1* 答案:哪怕輸入1也會走else里面的代碼,不影響功能,所以無需加“=”等于號*/if (isNaN(disNum) || disNum < 1) {disNum = 0;} else {//屬于正常情況(小數(shù):取證),帶給服務器變化的量 用戶輸入進來的 - 產(chǎn)品的起始個數(shù)disNum = parseInt(disNum) - car.skuNum;}break;}try {//派發(fā)actionawait this.$store.dispatch('addOrUpdateShopCar', {skuId: car.skuId, skuNum: disNum})//再一次獲取服務器最新的數(shù)據(jù)進行展示this.getData();} catch (error) {//失敗alert(error.message);}}, 500),
29.5刪除某一產(chǎn)品
修改代碼:
app/src/api/index.js
//刪除購物產(chǎn)品的接口
//URL:/api/cart/deleteCart/{skuId} method:DELETE
export const reqDeleteCartById = (skuId)=>requests({url:`/cart/deleteCart/${skuId}`,method:'delete'});
src/store/shopCar/index.js
import {reqDeleteCartById} from "@/api";const actions = {//刪除購物車某一個產(chǎn)品async reqDeleteCartById({commit}, skuId) {let response = await reqDeleteCartById(skuId);if (response.code == 200) {//返回的是成功的標記return "OK";} else {//返回的是失敗的標記return Promise.reject(new Error("fail"))}}
}
src/pages/ShopCart/index.vue
<a class="sindelet" @click="reqDeleteCartById(car.skuId)">刪除</a>//刪除某一個產(chǎn)品的操作
async reqDeleteCartById(skuId) {try {//派發(fā)actionawait this.$store.dispatch('reqDeleteCartById', skuId)this.getData();} catch (error) {alert(error.message)}
}
29.6修改產(chǎn)品狀態(tài)
修改代碼:
app/src/api/index.js
//修改商品的選中狀態(tài)
//URL:/api/cart/checkCart/{skuId}/{isChecked} method:get
export const reqUpdateCheckedByid = (skuId,isChecked)=>requests({url:`/cart/checkCart/${skuId}/${isChecked}`,method:'get'});
src/store/shopCar/index.js
import {reqUpdateCheckedByid} from "@/api";const actions = {//修改購物車某一個產(chǎn)品的選中狀態(tài)async reqUpdateCheckedByid({commit}, {skuId,isChecked}) {let response = await reqUpdateCheckedByid(skuId,isChecked);if (response.code == 200) {//返回的是成功的標記return "OK";} else {//返回的是失敗的標記return Promise.reject(new Error("fail"))}},
}
src/pages/ShopCart/index.vue
<input type="checkbox" name="chk_list" :checked="car.isChecked == 1" @change="reqUpdateCheckedByid(car.skuId, $event)">//修改某個產(chǎn)品的勾選狀態(tài)async reqUpdateCheckedByid(skuId, event) {try {//如果修改數(shù)據(jù)成功,再次獲取服務器數(shù)據(jù)(購物車)let isChecked = event.target.checked ? "1" : "0";//派發(fā)actionawait this.$store.dispatch('reqUpdateCheckedByid', {skuId: skuId, isChecked})this.getData();} catch (error) {alert(error.message)}},
29.7刪除全部選中的商品
修改代碼:
src/pages/ShopCart/index.vue
<a @click="deleteAllCheckedCar">刪除選中的商品</a>//刪除全部選中的產(chǎn)品
//這個回調(diào)函數(shù)咱門沒辦法手機到一些有用數(shù)據(jù)
async deleteAllCheckedCar() {try {//成功//派發(fā)一個actionawait this.$store.dispatch('deleteAllCheckedCar')//再發(fā)請求獲取購物車列表this.getData()} catch (error) {//失敗alert(error.message)}
}
src/store/shopCar/index.js
//刪除全部勾選的產(chǎn)品
async deleteAllCheckedCar({dispatch, getters}) {//context:小倉庫,commit【提交mutations修改state】 getters【計算屬性】 dispatch【派發(fā)action】 state【當前倉庫數(shù)據(jù)】//獲取購物車中全部的產(chǎn)品(是一個數(shù)組)let primoseAll = [];getters.carList.cartInfoList.forEach(item => {let promise = item.isChecked == 1 ? dispatch('reqDeleteCartById', item.skuId) : '';//將每一次返回的Promise添加到數(shù)組當中primoseAll.push(promise);})//只要全部的p1|p2....都成功,返回結(jié)果即為成功//如果有一個失敗,返回即為失敗結(jié)果return Promise.all(primoseAll);}
注意點1:接口API未提供選中刪除的功能,只提供了單獨刪除的,所以可以采用批量循環(huán)刪除的方式。
注意點2:dispatch派發(fā)不僅可以存在于vue中使用,也可以在vuex倉庫中使用
注意點3:vuex倉庫中的context包含很多東西,包括【commit、dispatch、getters、state…】,具體如圖
注意點4:Promise.all用法,all里面的是個數(shù)組,如果其中的子項promise有一個失敗,返回即為失敗結(jié)果。具體用法如下:
let primoseAll = [];
let promise = item.isChecked == 1 ? dispatch('reqDeleteCartById', item.skuId) : '';
//將每一次返回的Promise添加到數(shù)組當中
primoseAll.push(promise);
//只要全部的p1|p2....都成功,返回結(jié)果即為成功
//如果有一個失敗,返回即為失敗結(jié)果
return Promise.all(primoseAll);
29.8全選操作
修改代碼:
src/pages/ShopCart/index.vue
<input class="chooseAll" type="checkbox" :checked="isAllChecked && cartInfoList.length > 0" @click="updateAllCheckedCar($event.target.checked)">//修改全部產(chǎn)品的選中狀態(tài)
async updateAllCheckedCar(checked) {try {//成功//派發(fā)一個actionlet isChecked = checked ? "1" : "0";await this.$store.dispatch('updateAllCheckedCar', isChecked)//再發(fā)請求獲取購物車列表this.getData()} catch (error) {//失敗alert(error.message)}
},
src/store/shopCar/index.js
//修改全部產(chǎn)品的狀態(tài)
async updateAllCheckedCar({dispatch, getters}, isChecked) {//context:小倉庫,commit【提交mutations修改state】 getters【計算屬性】 dispatch【派發(fā)action】 state【當前倉庫數(shù)據(jù)】//獲取購物車中全部的產(chǎn)品(是一個數(shù)組)let primoseAll = [];getters.carList.cartInfoList.forEach(item => {let promise = dispatch('reqUpdateCheckedByid', {skuId:item.skuId, isChecked});//將每一次返回的Promise添加到數(shù)組當中primoseAll.push(promise);})//只要全部的p1|p2....都成功,返回結(jié)果即為成功//如果有一個失敗,返回即為失敗結(jié)果return Promise.all(primoseAll);}
注意點1:全選或全不選后的正確效果如圖
注意點2:
問題:全部刪除后,左下角的勾選按鈕居然還是選中狀態(tài),需要優(yōu)化
答案:在后面多補充個cartInfoList.length > 0判斷條件即可
:checked="isAllChecked && cartInfoList.length > 0
本人其他相關(guān)文章鏈接
1.vue尚品匯商城項目-day04【24.點擊搜索按鈕跳轉(zhuǎn)后的頁面商品列表、平臺售賣屬性動態(tài)展示(開發(fā)Search組件)】
2.vue尚品匯商城項目-day04【25.面包屑處理關(guān)鍵字】
3.vue尚品匯商城項目-day04【26.排序操作(難點)】
4.vue尚品匯商城項目-day04【27.分頁器靜態(tài)組件(難點)】
5.vue尚品匯商城項目-day04【28.詳情頁面Detail】
6.vue尚品匯商城項目-day04【29.加入購物車操作(難點)】