一、为什么用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 });
		}
	}
};

基本就这些,有问题或者建议可以留言。

Logo

前往低代码交流专区

更多推荐