vue之vuex實現購物車功能

一、爲什麼用vuex來實現購物車功能

原本項目是沒有完全用vuex來實現的,但購物車的一些公共狀態,還有方法很混亂,最後爲了開發維護使用方便就用了。購物車有很多實現方式,適合就好。

二、用到的vuex知識點。

  • module模塊化,namespaced命名空間
  • state, actions, mutations,getters主要用法
  • 輔助函數,方法調用。

vue之狀態管理器vuex(三) 這是另外一篇的用法

三、store結構,主要文件用法。

store結構

  • modules:按照功能劃分的vuex模塊,一般構建大些的項目時,條理更加清晰,便於維護開發。這裏主要說 cart.js 購物車功能
  • index.js : store的入口文件,各功能的繼承。
  • type.js : 定義方法常量,大寫字母加下劃線構成,可用可不用,根據情況。
  • 在app.vue中引入掛載,上個文章裏有,不多說。
  1. 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

  1. 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 });
		}
	}
};

基本就這些,有問題或者建議可以留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章