一、爲什麼用vuex來實現購物車功能
原本項目是沒有完全用vuex來實現的,但購物車的一些公共狀態,還有方法很混亂,最後爲了開發維護使用方便就用了。購物車有很多實現方式,適合就好。
二、用到的vuex知識點。
- module模塊化,namespaced命名空間
- state, actions, mutations,getters主要用法
- 輔助函數,方法調用。
vue之狀態管理器vuex(三) 這是另外一篇的用法
三、store結構,主要文件用法。
- modules:按照功能劃分的vuex模塊,一般構建大些的項目時,條理更加清晰,便於維護開發。這裏主要說 cart.js 購物車功能
- index.js : store的入口文件,各功能的繼承。
- type.js : 定義方法常量,大寫字母加下劃線構成,可用可不用,根據情況。
- 在app.vue中引入掛載,上個文章裏有,不多說。
- index.js (功能介紹都寫在代碼註釋裏吧)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//引入modules模塊
import cart from './modules/cart.js'
//實例化vuex爲store模塊,掛載上cart,在下面導出,在app.vue引入掛載全局。
const store = new Vuex.Store({
modules: {
cart
}
})
export default store
- cart.js (購物車功能都在這裏了)
代碼中用到的一些uni-app接口方法,可根據實際情況替換。
// 引入請求數據接口的封裝,每人實現和用法不一樣。引入store,爲了用一些方法。
import http from '@/common/request/index'
import store from '@/common/store'
// vuex方法常量的引入,讓vuex的功能更細清晰,可用可不用,看需要。
import {
CART_LIST,
CART_NUM
} from '../types.js'
// vuex中state模塊,定義當前功能用到的變量數據,類似data的初始化數據
// 頁面調用:this.$store.state.cart.變量名
const state = {
cartList: [], //購物車數據。
allSelected: false, //購物車的全選狀態。
cartNum: uni.getStorageSync('cartNum') ? uni.getStorageSync('cartNum') : '', //購物車,涉及到刷新數據丟失,所以存了本地,接口是uni.app框架的。
}
// vuex中actions模塊,主要定義一些異步方法。
// 頁面觸發調用:this.$store.dispatch('方法名',參數只能有一個)
/**
*action和mutation都可以改變state中數據的狀態,但是action可以處理異步函數可以在devtool中追 *蹤數據變化,而mutation只可以處理同步函數,當處理異步函數的時候檢測不到數據變化;
*/
const actions = {
// 購物車數據(查)
getCartList({
commit,
state
}) {
return new Promise((resolve, reject) => {
http('cartList').then(res => { //請求數據,無傳參。
let cartData = res.data;
cartData.map(item => { // 重構購物車數據,加入選中狀態,做單選多選用。
item.checked = false;
})
uni.setStorageSync('cartNum', cartData.length); //購物車數量
commit('CART_LIST', cartData); // 重構後的數據,提交給commit,觸發數據更新。
commit('checkCartList'); // 每次請求購物車數據,做一次全選檢測(全選時候加入新的購物車商品場景)
}).catch(e => {
reject(e)
})
})
},
// 添加到購物車(增)
addCartGoods({
commit
}, data) {
return new Promise((resolve, reject) => {
http('cartAdd', { // 添加購物車,傳入商品id.
goodsId: data.id,
}).then(res => {
resolve(res)
store.dispatch('getCartList'); //更新購物車數。
}).catch(e => {
reject(e)
})
})
},
// 刪除購物車商品(刪)
changeCartList({
commit,
state,
dispatch
}, param) {
return new Promise((resolve, reject) => {
http('cartDelete', { // 刪除購物車商品,傳入ids;
cartIds: param.ids,
}).then(res => {
if (res.code === 1) {
dispatch('getCartList');//刪除後,更新購物車。
}
}).catch(e => {
reject(e)
})
})
},
}
// vuex中mutations,主要用來觸發數據更新,一些數據的同步操作。
// 頁面分發調用:this.$store.commit('方法名',參數只能有一個)
const mutations = {
// cart數據獲取變動。
[CART_LIST](state, data) {
state.cartList = data
},
// 切換全選。
changeAllSellect(state) {
state.allSelected = !state.allSelected;
},
// 全選設置,傳入全選按鈕的狀態。
getAllSellectCartList(state, flag) {
state.cartList.map(item => {
item.checked = flag
})
},
// 單選設置,傳入單選的商品下標,改變它的選中狀態。
selectItem(
state, {
index,
flag
}) {
state.cartList[index].checked = !flag;
store.commit('checkCartList') // 每次單選,都要檢測是否全部選中了。
},
// 全選檢測
checkCartList(state) {
let all = true;
state.cartList.map(item => {
if (!item.checked) { // 枚舉購物車數據,默認是全選,有一個沒被選中,全選爲false。
all = false
}
})
state.allSelected = all; // 更改全選狀態。
}
}
//vuex中的getter,類似vue的computed計算屬性,惰性動態監聽計算數據,二次處理數據用。
// 頁面調用:this.$store.getters.getters中的變量名(注意不是state中的)
const getters = {
// 購物車數量和總價
totalCount: state => {
let totalNum = 0;
let totalPrice = 0;
state.cartList.filter(item => {
if (item.checked) { // 篩選選中的商品,實時計算價格,數量。
totalNum += 1;
totalPrice += item.goods_num * item.sku_price.price;
}
})
return {
totalNum,
totalPrice
}
},
}
export default {
//namespaced:true,命名空間,防止方法污染,根據情況用。
state,
mutations,
actions,
getters
}
四、購物車頁面的主要使用(部分代碼)
// 引入vuex 輔助函數,上面每個模塊在頁面中的用法也可以,推薦輔助函數。
import { mapMutations, mapActions, mapState, mapGetters } from 'vuex';
export default
computed: {
...mapState({
cartList: ({ cart }) => cart.cartList,//在計算屬性中獲取vuex的數據,解構的cart模塊,然後取值賦值。
allSel: ({ cart }) => cart.allSelected
}),
...mapGetters(['totalCount'])//直接拿getters中的處理過的數據。
},
created() {
this.getCartList();//獲取頁面數據。
},
methods: {
...mapActions(['getCartList', 'changeCartList']),//在這拿actions中的方法。
// 單選
onSel(index, flag) { //傳入單選的下標,和選中狀態,在vuex中接收。
let that = this;
that.$store.commit('selectItem', { index, flag });
},
// 全選
onAllSel() {
let that = this;
that.$store.commit('changeAllSellect'); //按鈕切換全選。
that.$store.commit('getAllSellectCartList', that.allSel); //列表全選
},
// 刪除
goodsDelete() {
let that = this;
let { cartList } = this;
let ids= [];
cartList.map(item => { //枚舉出選中的商品,把id放入數組,傳給vuex方法。
if (item.checked) {
ids.push(item.id);
}
});
this.changeCartList({ ids: ids });
}
}
};
基本就這些,有問題或者建議可以留言。