7.配置页面 - 加入购物车
(1).创建 cart 分支
git checkout -b cart
(2). 配置 vuex (uniapp封装了Vue不用安装vuex)
- 在项目根目录中创建 store 文件夹,专门用来存放 vuex 相关的模块
- 在 store 目录上鼠标右键,选择 新建 -> js文件,新建 store.js 文件:
store.js
// 1. 导入 Vue 和 Vuex import Vue from 'vue' import Vuex from 'vuex' // 2. 将 Vuex 安装为 Vue 的插件 Vue.use(Vuex) // 3. 创建 Store 的实例对象 const store = new Vuex.Store({ // TODO:挂载 store 模块 modules: {}, }) // 4. 向外共享 Store 的实例对象 export default store
- 在 main.js 中导入 store 实例对象并挂载到 Vue 的实例上:
// 1. 导入 store 的实例对象 import store from './store/store.js' // 省略其它代码... const app = new Vue({ ...App, // 2. 将 store 挂载到 Vue 实例上 store, }) app.$mount()
(3). 创建购物车的 store 模块
- 在
store
目录上鼠标右键,选择新建 -> js
文件,创建购物车的store
模块,命名为cart.js
:
2. 在 cart.js 中,初始化如下的 vuex 模块:
export default { // 1.开启命名空间 namespaced: true, // 返回数据节点 state: () => ({ // 购物车的数组,用来存储购物车中每个商品的信息对象 // 每个商品的信息对象,都包含如下 6 个属性: // { goods_id, goods_name, goods_price, goods_count, goods_small_logo, goods_state } cart: [] }), mutations: {}, getters: {} }
- 在 store/store.js 模块中,导入并挂载购物车的 vuex 模块,示例代码如下:
import Vue from 'vue' import Vuex from 'vuex' // 1. 导入购物车的 vuex 模块 import moduleCart from './cart.js' Vue.use(Vuex) const store = new Vuex.Store({ // TODO:挂载 store 模块 modules: { // 2. 挂载购物车的 vuex 模块,模块内成员的访问路径被调整为 m_cart,例如: // 购物车模块中 cart 数组的访问路径是 m_cart/cart m_cart: moduleCart, }, }) export default store
(4).在商品详情页中使用 Store 中的数据
- 在
goods_detail.vue
页面中,修改
// 从 vuex 中按需导出 mapState 辅助方法 import { mapState } from 'vuex' export default { computed: { // 调用 mapState 方法,把 m_cart 模块中的 cart 数组映射到当前页面中,作为计算属性来使用 // ...mapState('模块的名称', ['要映射的数据名称1', '要映射的数据名称2']) ...mapState('m_cart', ['cart']), }, // 省略其它代码... }
注意:今后无论映射 mutations 方法,还是 getters 属性,还是 state 中的数据,都需要指定模块的名称,才能进行映射。
- 在页面渲染时,可以直接使用映射过来的数据,例如
<!-- 运费 --> <view class="yf">快递:免运费 -- {{cart.length}}</view>
(5).实现加入购物车的功能
- 在
store
目录下的cart.js
模块中,封装一个将商品信息加入购物车的mutations
方法,命名为addToCart
。示例代码如下:
Vuex共享的数据只有在mutations这个对象中才能进行修改
mutations: { addToCart(state, item) { // 第一个参数:不占位置、第二个参数: 对象 // findReusult : 要么得到undefind->没有找到信息(false) 要么得到商品的对象(true) const findReusult = state.cart.find(x => x.goods_id === item.goods_id) //这里会遍历catr数组,并得到对象x。然后进行判断购物车里存放的和添加的是否一致 if (!findReusult) { // 加入说undefind state.cart.push(item) // 推入cart数组 } else { //加入说已经存在 那么就自增1 findReusult.goods_count++ } } },
export default { // 1.开启命名空间 namespaced: true, // 返回数据节点 state: () => ({ // 购物车的数组,用来存储购物车中每个商品的信息对象 // 每个商品的信息对象,都包含如下 6 个属性: // { goods_id, goods_name, goods_price, goods_count, goods_small_logo, goods_state } cart: [] }), mutations: { addToCart(state, item) { // 第一个参数:返回值的名(调用cart的不占位置)、第二个参数: 对象 // findReusult : 要么得到undefind->没有找到信息(false) 要么得到商品的对象(true) const findReusult = state.cart.find(x => x.goods_id === item.goods_id) //这里会遍历catr数组,并得到对象x。然后进行判断购物车里存放的和添加的是否一致 if (!findReusult) { // 加入说undefind state.cart.push(item) // 推入cart数组 } else { //加入说已经存在 那么就自增1 findReusult.goods_count++ } } }, getters: {} }
- 在商品详情页面中,通过
mapMutations
这个辅助方法,把vuex
中m_cart
模块下的addToCart
方法映射到当前页面:
// 按需导入 mapMutations 这个辅助方法 import { mapMutations } from 'vuex' export default { methods: { // 把 m_cart 模块中的 addToCart 方法映射到当前页面使用 ...mapMutations('m_cart', ['addToCart']), }, }
- 为商品导航组件
uni-goods-nav
绑定@buttonClick="buttonClick"
事件处理函数:
goods_deatil
// 右侧的信息 buttonClick(e) { console.log(e) 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 // 商品的勾选状态 } // 调用共享的方法 ⭐ this.addToCart(goods) console.log(this.goods_info) }
(6). 动态统计购物车中商品的总数量
cart.js
编写计算属性: 一个方法出现return就会变成计算属性
监听的是: 假如说点击加入购物车的话,那么cart就会变化。cart只要变化就会引出c变化,c一变化就会触发监听事件
getters: { total(state) { let c = 0 state.cart.forEach(item => c += item.goods_count) return c } }
cart.vue
// 引入Vuex import { // 映射属性 mapState, // 映射方法增删改 mapMutations, // 映射方法 读 mapGetters } from "vuex" watch: { // 调用计算属性 total,假如 total(newValue) { // 这个方法是: 在一个未知的数组对象中找哪一个对象的text属性为"购物车"的这个对象。 const findResult = this.options.find(item => item.text === '购物车') if (findResult) { // 加入说找到了就赋值新的值 findResult.info = newValue } } },
(7).持久化存储购物车的功能
// 持久化存储本地数据 saveToStorage(state) { uni.setStorageSync('cart', JSON.stringify(state.cart)) }
- 修改 mutations 节点中的
addToCart
方法,在处理完商品信息后,调用步骤 1 中定义的saveToStorage
方法:
// 通过 commit 方法,调用 m_cart 命名空间下的 saveToStorage 方法 this.commit('m_cart/saveToStorage')
- 修改 cart.js 模块中的 state 函数,读取本地存储的购物车数据,对 cart 数组进行初始化:
// 模块的 state 数据 state: () => ({ // 购物车的数组,用来存储购物车中每个商品的信息对象 // 每个商品的信息对象,都包含如下 6 个属性: // { goods_id, goods_name, goods_price, goods_count, goods_small_logo, goods_state } cart: JSON.parse(uni.getStorageSync('cart') || '[]') }),