1.在项目根目录中创建 store
文件夹,专门用来存放 vuex
相关的模块
2.新建 store.js
文件并配置:
// 1. 导入 Vue 和 Vuex
import Vue from 'vue'
import Vuex from 'vuex'
// 1. 导入购物车的 vuex 模块
import moduleCart from './cart.js'
// 导入用户的 vuex 模块
import moduleUser from './user.js'
// 2. 将 Vuex 安装为 Vue 的插件
Vue.use(Vuex)
// 3. 创建 Store 的实例对象
const store = new Vuex.Store({
// TODO:挂载 store 模块
modules: {
// 2. 挂载购物车的 vuex 模块,模块内成员的访问路径被调整为 m_cart,例如:
// 购物车模块中 cart 数组的访问路径是 m_cart/cart
m_cart: moduleCart,
// 挂载用户的 vuex 模块,访问路径为 m_user
m_user: moduleUser,
},
})
// 4. 向外共享 Store 的实例对象
export default store
1.在 store.js
同目录下创建cart.js
。
2.实现加入购物车的功能addToCart
。
3.实现动态监听统计购物车中商品的总数量的total
方法。
4.实现购物车中的商品的持久化存储saveToStorage
。
export default {
// 为当前模块开启命名空间
namespaced: true,
// 模块的 state 数据
state: () => ({
// 购物车的数组,用来存储购物车中每个商品的信息对象
// 每个商品的信息对象,都包含如下 6 个属性:
// { goods_id, goods_name, goods_price, goods_count, goods_small_logo, goods_state }
cart: JSON.parse(uni.getStorageSync('cart') || '[]')
}),
// 模块的 mutations 方法
mutations: {
// 将购物车中的数据持久化存储到本地
saveToStorage(state) {
uni.setStorageSync('cart', JSON.stringify(state.cart))
},
addToCart(state, goods) {
// 根据提交的商品的Id,查询购物车中是否存在这件商品
// 如果不存在,则 findResult 为 undefined;否则,为查找到的商品信息对象
const findResult = state.cart.find((x) => x.goods_id === goods.goods_id)
if (!findResult) {
// 如果购物车中没有这件商品,则直接 push
state.cart.push(goods)
} else {
// 如果购物车中有这件商品,则只更新数量即可
findResult.goods_count++
}
// 通过 commit 方法,调用 m_cart 命名空间下的 saveToStorage 方法
this.commit('m_cart/saveToStorage')
},
// 更新购物车中商品的勾选状态
updateGoodsState(state, goods) {
// 根据 goods_id 查询购物车中对应商品的信息对象
const findResult = state.cart.find(x => x.goods_id === goods.goods_id)
// 有对应的商品信息对象
if (findResult) {
// 更新对应商品的勾选状态
findResult.goods_state = goods.goods_state
// 持久化存储到本地
this.commit('m_cart/saveToStorage')
}
},
// 更新购物车中商品的数量
updateGoodsCount(state, goods) {
// 根据 goods_id 查询购物车中对应商品的信息对象
const findResult = state.cart.find(x => x.goods_id === goods.goods_id)
if(findResult) {
// 更新对应商品的数量
findResult.goods_count = goods.goods_count
// 持久化存储到本地
this.commit('m_cart/saveToStorage')
}
},
// 根据 Id 从购物车中删除对应的商品信息
removeGoodsById(state, goods_id) {
// 调用数组的 filter 方法进行过滤
state.cart = state.cart.filter(x => x.goods_id !== goods_id)
// 持久化存储到本地
this.commit('m_cart/saveToStorage')
},
// 更新所有商品的勾选状态
updateAllGoodsState(state, newState) {
// 循环更新购物车中每件商品的勾选状态
state.cart.forEach(x => x.goods_state = newState)
// 持久化存储到本地
this.commit('m_cart/saveToStorage')
}
},
// 模块的 getters 属性
getters: {
// 统计购物车中商品的总数量
total(state) {
let c = 0
// 循环统计商品的数量,累加到变量 c 中
state.cart.forEach(goods => c += goods.goods_count)
return c
},
// 勾选的商品的总数量
checkedCount(state) {
// 先使用 filter 方法,从购物车中过滤器已勾选的商品
// 再使用 reduce 方法,将已勾选的商品总数量进行累加
// reduce() 的返回值就是已勾选的商品的总数量
return state.cart.filter(x => x.goods_state).reduce((total, item) => total += item.goods_count, 0)
},
// 已勾选的商品的总价
checkedGoodsAmount(state) {
// 先使用 filter 方法,从购物车中过滤器已勾选的商品
// 再使用 reduce 方法,将已勾选的商品数量 * 单价之后,进行累加
// reduce() 的返回值就是已勾选的商品的总价
// 最后调用 toFixed(2) 方法,保留两位小数
return state.cart.filter(x => x.goods_state)
.reduce((total, item) => total += item.goods_count * item.goods_price, 0)
.toFixed(2)
}
}
}
1.引入store
的数据:
<script>
// 从 vuex 中按需导出 mapState 辅助方法
import { mapState } from 'vuex'
export default {
computed: {
// 调用 mapState 方法,把 m_cart 模块中的 cart 数组映射到当前页面中,作为计算属性来使用
// ...mapState('模块的名称', ['要映射的数据名称1', '要映射的数据名称2'])
...mapState('m_cart', ['cart']),
},
}
</script>
2,引入store
的方法“商品添加到购物车addToCart
”,并为商品导航组件 uni-goods-nav
绑定 @buttonClick="buttonClick"
事件处理函数:
<script>
// 按需导入 mapMutations 这个辅助方法
import { mapMutations } from 'vuex'
export default {
methods: {
// 把 m_cart 模块中的 addToCart 方法映射到当前页面使用
...mapMutations('m_cart', ['addToCart']),
// 右侧按钮的点击事件处理函数
buttonClick(e) {
// 1. 判断是否点击了 加入购物车 按钮
if (e.content.text === '加入购物车') {
// 2. 组织一个商品的信息对象
const goods = {
goods_id: this.goods_info.goods_id, // 商品的Id
goods_name: this.goods_info.goods_name, // 商品的名称
goods_price: this.goods_info.goods_price, // 商品的价格
goods_count: 1, // 商品的数量
goods_small_logo: this.goods_info.goods_small_logo, // 商品的图片
goods_state: true // 商品的勾选状态
}
// 3. 通过 this 调用映射过来的 addToCart 方法,把商品信息对象存储到购物车中
this.addToCart(goods)
}
}
},
}
</script>
1.在项目根目录中新建 mixins
文件夹,并在 mixins
文件夹之下新建 tabbar-badge.js
文件
2.将设置 tabBar
徽标的代码抽离为 mixins
import { mapGetters } from 'vuex'
// 导出一个 mixin 对象
export default {
computed: {
...mapGetters('m_cart', ['total']),
},
watch: {
// 监听 total 值的变化
total() {
// 调用 methods 中的 setBadge 方法,重新为 tabBar 的数字徽章赋值
this.setBadge()
},
},
onShow() {
// 在页面刚展示的时候,设置数字徽标
this.setBadge()
},
methods: {
setBadge() {
// 调用 uni.setTabBarBadge() 方法,为购物车设置右上角的徽标
uni.setTabBarBadge({
index: 2,
text: this.total + '', // 注意:text 的值必须是字符串,不能是数字
})
},
},
}
3.修改 home.vue
,cate.vue
,cart.vue
,my.vue
这 4 个 tabBar
页面的源代码,分别导入 @/mixins/tabbar-badge.js
模块并进行使用:
// 导入自己封装的 mixin 模块
import badgeMix from '@/mixins/tabbar-badge.js'
export default {
// 将 badgeMix 混入到当前的页面中进行使用
mixins: [badgeMix],
// 省略其它代码...
}