微信小程序开发(九)- uni-app微信小程序商城

目录

八、加入购物车

[8.0 创建 cart 分支](#8.0 创建 cart 分支)

[8.1 配置 vuex](#8.1 配置 vuex)

[8.2 创建购物车的 store 模块](#8.2 创建购物车的 store 模块)

[8.3 在商品详情页中使用 Store 中的数据](#8.3 在商品详情页中使用 Store 中的数据)

[8.4 实现加入购物车的功能](#8.4 实现加入购物车的功能)

[8.5 动态统计购物车中商品的总数量](#8.5 动态统计购物车中商品的总数量)

[8.6 持久化存储购物车中的商品](#8.6 持久化存储购物车中的商品)

[8.7 优化商品详情页的 total 侦听器](#8.7 优化商品详情页的 total 侦听器)

[8.8 动态为 tabBar 页面设置数字徽标](#8.8 动态为 tabBar 页面设置数字徽标)

[8.9 将设置 tabBar 徽标的代码抽离为 mixins](#8.9 将设置 tabBar 徽标的代码抽离为 mixins)

九、购物车页面

[9.0 创建购物车页面的编译模式](#9.0 创建购物车页面的编译模式)

[9.1 商品列表区域](#9.1 商品列表区域)

[9.1.1 渲染购物车商品列表的标题区域](#9.1.1 渲染购物车商品列表的标题区域)

[9.1.2 渲染商品列表区域的基本结构](#9.1.2 渲染商品列表区域的基本结构)

[9.1.3 为 my-goods 组件封装 radio 勾选状态](#9.1.3 为 my-goods 组件封装 radio 勾选状态)

[9.1.4 为 my-goods 组件封装 radio-change 事件](#9.1.4 为 my-goods 组件封装 radio-change 事件)

[9.1.5 修改购物车中商品的勾选状态](#9.1.5 修改购物车中商品的勾选状态)

[9.1.6 为 my-goods 组件封装 NumberBox](#9.1.6 为 my-goods 组件封装 NumberBox)

[9.1.7 为 my-goods 组件封装 num-change 事件](#9.1.7 为 my-goods 组件封装 num-change 事件)

[9.1.8 解决 NumberBox 数据不合法的问题](#9.1.8 解决 NumberBox 数据不合法的问题)

[9.1.9 完善 NumberBox 的 inputValue 侦听器](#9.1.9 完善 NumberBox 的 inputValue 侦听器)

[9.1.10 修改购物车中商品的数量](#9.1.10 修改购物车中商品的数量)

[9.1.11 渲染滑动删除的 UI 效果](#9.1.11 渲染滑动删除的 UI 效果)

[9.1.12 实现滑动删除的功能](#9.1.12 实现滑动删除的功能)

[9.2 收货地址区域](#9.2 收货地址区域)

[9.2.1 创建收货地址组件](#9.2.1 创建收货地址组件)

[9.2.2 实现收货地址区域的按需展示](#9.2.2 实现收货地址区域的按需展示)

[9.2.3 实现选择收货地址的功能](#9.2.3 实现选择收货地址的功能)

[9.2.4 将 address 信息存储到 vuex 中](#9.2.4 将 address 信息存储到 vuex 中)

[9.2.5 将 Store 中的 address 持久化存储到本地](#9.2.5 将 Store 中的 address 持久化存储到本地)

[9.2.6 将 addstr 抽离为 getters](#9.2.6 将 addstr 抽离为 getters)

[9.2.7 重新选择收货地址](#9.2.7 重新选择收货地址)

[9.2.8 解决收货地址授权失败的问题](#9.2.8 解决收货地址授权失败的问题)

[9.2.9 解决 iPhone 真机上无法重新授权的问题](#9.2.9 解决 iPhone 真机上无法重新授权的问题)

[9.3 结算区域](#9.3 结算区域)

[9.3.1 把结算区域封装为组件](#9.3.1 把结算区域封装为组件)

[9.3.2 渲染结算区域的结构和样式](#9.3.2 渲染结算区域的结构和样式)

[9.3.3 动态渲染已勾选商品的总数量](#9.3.3 动态渲染已勾选商品的总数量)

[9.3.4 动态渲染全选按钮的选中状态](#9.3.4 动态渲染全选按钮的选中状态)

[9.3.5 实现商品的全选/反选功能](#9.3.5 实现商品的全选/反选功能)

[9.3.6 动态渲染已勾选商品的总价格](#9.3.6 动态渲染已勾选商品的总价格)

[9.3.7 动态计算购物车徽标的数值](#9.3.7 动态计算购物车徽标的数值)

[9.3.8 渲染购物车为空时的页面结构](#9.3.8 渲染购物车为空时的页面结构)

[9.4 分支的合并与提交](#9.4 分支的合并与提交)

八、加入购物车

8.0 创建 cart 分支

运行如下的命令,基于 master 分支在本地创建 cart 子分支,用来开发购物车相关的功能:

bash 复制代码
git checkout -b cart

8.1 配置 vuex

  1. 在项目根目录中创建 store 文件夹,专门用来存放 vuex 相关的模块

  2. store 目录上鼠标右键,选择 新建 -> js文件,新建 store.js 文件:

  1. store.js 中按照如下 4 个步骤初始化 Store 的实例对象
  1. main.js 中导入 store 实例对象并挂载到 Vue 的实例上:

8.2 创建购物车的 store 模块

  1. store 目录上鼠标右键,选择 新建 -> js文件,创建购物车的 store 模块,命名为 cart.js
  1. cart.js 中,初始化如下的 vuex 模块:
  1. store/store.js 模块中,导入并挂载购物车的 vuex 模块,示例代码如下:

8.3 在商品详情页中使用 Store 中的数据

  1. goods_detail.vue 页面中,修改 <script></script> 标签中的代码如下:

注意:今后无论映射 mutations 方法,还是 getters 属性,还是 state 中的数据,都需要指定模块的名称,才能进行映射。

  1. 在页面渲染时,可以直接使用映射过来的数据,例如:

8.4 实现加入购物车的功能

  1. 在 store 目录下的 cart.js 模块中,封装一个将商品信息加入购物车的 mutations 方法,命名为 addToCart。示例代码如下:
  1. 在商品详情页面中,通过 mapMutations 这个辅助方法,把 vuex 中 m_cart 模块下的 addToCart 方法映射到当前页面:
  1. 为商品导航组件 uni-goods-nav 绑定 @buttonClick="buttonClick" 事件处理函数:

8.5 动态统计购物车中商品的总数量

  1. cart.js 模块中,在 getters 节点下定义一个 total 方法,用来统计购物车中商品的总数量:
  1. 在商品详情页面的 script 标签中,按需导入 mapGetters 方法并进行使用:
  1. 通过 watch 侦听器,监听计算属性 total 值的变化,从而动态为购物车按钮的徽标赋值

8.6 持久化存储购物车中的商品

  1. cart.js 模块中,声明一个叫做 saveToStorage 的 mutations 方法,此方法负责将购物车中的数据持久化存储到本地:
  1. 修改 mutations 节点中的 addToCart 方法,在处理完商品信息后,调用步骤 1 中定义的 saveToStorage 方法:
  1. 修改 cart.js 模块中的 state 函数,读取本地存储的购物车数据,对 cart 数组进行初始化:

8.7 优化商品详情页的 total 侦听器

  1. 使用普通函数的形式 定义的 watch 侦听器,在页面首次加载后不会被调用。因此导致了商品详情页在首次加载完毕之后,不会将商品的总数量显示到商品导航区域:
  1. 为了防止这个上述问题,可以使用对象的形式来定义 watch 侦听器(详细文档请参考 Vue 官方的 watch 侦听器教程),示例代码如下:

8.8 动态为 tabBar 页面设置数字徽标

需求描述:从商品详情页面导航到购物车页面之后,需要为 tabBar 中的购物车动态设置数字徽标。

  1. 把 Store 中的 total 映射到 cart.vue 中使用:
  1. 在页面刚显示出来的时候,立即调用 setBadge 方法,为 tabBar 设置数字徽标:
  1. methods 节点中,声明 setBadge 方法如下,通过 uni.setTabBarBadge() 为 tabBar 设置数字徽标:

8.9 将设置 tabBar 徽标的代码抽离为 mixins

注意:除了要在 cart.vue 页面中设置购物车的数字徽标,还需要在其它 3 个 tabBar 页面中,为购物车设置数字徽标。
此时可以使用 Vue 提供的 mixins 特性,提高代码的可维护性。

  1. 在项目根目录中新建 mixins 文件夹,并在 mixins 文件夹之下新建 tabbar-badge.js 文件,用来把设置 tabBar 徽标的代码封装为一个 mixin 文件:
  1. 修改 home.vuecate.vuecart.vuemy.vue 这 4 个 tabBar 页面的源代码,分别导入 @/mixins/tabbar-badge.js 模块并进行使用:

九、购物车页面

9.0 创建购物车页面的编译模式

  1. 打开微信开发者工具,点击工具栏上的"编译模式"下拉菜单,选择"添加编译模式":
  1. 勾选"启动页面的路径"之后,点击"确定"按钮,新增购物车页面的编译模式:

9.1 商品列表区域

9.1.1 渲染购物车商品列表的标题区域

  1. 定义如下的 UI 结构:
  1. 美化样式:

9.1.2 渲染商品列表区域的基本结构

  1. 通过 mapState 辅助函数,将 Store 中的 cart 数组映射到当前页面中使用:
  1. 在 UI 结构中,通过 v-for 指令循环渲染自定义的 my-goods 组件:

9.1.3 为 my-goods 组件封装 radio 勾选状态

  1. 打开 my-goods.vue 组件的源代码,为商品的左侧图片区域添加 radio 组件:
  1. 给类名为 goods-item-leftview 组件添加样式,实现 radio 组件和 image 组件的左右布局:
  1. 封装名称为 showRadioprops 属性,来控制当前组件中是否显示 radio 组件:
  1. 使用 v-if 指令控制 radio 组件的按需展示:
  1. cart.vue 页面中的商品列表区域,指定 :show-radio="true" 属性,从而显示 radio 组件:
  1. 修改 my-goods.vue 组件,动态为 radio 绑定选中状态:

9.1.4 为 my-goods 组件封装 radio-change 事件

  1. 当用户点击 radio 组件,希望修改当前商品的勾选状态 ,此时用户可以为 my-goods 组件绑定 @radio-change 事件,从而获取当前商品的 goods_idgoods_state

定义 radioChangeHandler 事件处理函数如下:

  1. my-goods.vue 组件中,为 radio 组件绑定 @click 事件处理函数如下:
  1. my-goods.vue 组件的 methods 节点中,定义 radioClickHandler 事件处理函数:

9.1.5 修改购物车中商品的勾选状态

  1. store/cart.js 模块中,声明如下的 mutations 方法,用来修改对应商品的勾选状态:
  1. cart.vue 页面中,导入 mapMutations 这个辅助函数,从而将需要的 mutations 方法映射到当前页面中使用:

9.1.6 为 my-goods 组件封装 NumberBox

注意:NumberBox 组件是 uni-ui 提供的

  1. 修改 my-goods.vue 组件的源代码,在类名为 goods-info-box 的 view 组件内部渲染 NumberBox 组件的基本结构:
  1. 美化页面的结构:
  1. my-goods.vue 组件中,动态为 NumberBox 组件绑定商品的数量值:
  1. my-goods.vue 组件中,封装名称为 showNumprops 属性,来控制当前组件中是否显示 NumberBox 组件:
  1. my-goods.vue 组件中,使用 v-if 指令控制 NumberBox 组件的按需展示:
  1. cart.vue 页面中的商品列表区域,指定 :show-num="true" 属性,从而显示 NumberBox 组件:

9.1.7 为 my-goods 组件封装 num-change 事件

  1. 当用户修改了 NumberBox 的值以后,希望将最新的商品数量更新到购物车中,此时用户可以为 my-goods 组件绑定 @num-change 事件,从而获取当前商品的 goods_idgoods_count:
html 复制代码
<!-- 商品列表区域 -->
<block v-for="(goods, i) in cart" :key="i">
  <my-goods :goods="goods" :show-radio="true" :show-num="true" @radio-change="radioChangeHandler" @num-change="numberChangeHandler"></my-goods>
</block>

定义 numberChangeHandler 事件处理函数如下:

  1. my-goods.vue 组件中,为 uni-number-box 组件绑定 @change 事件处理函数如下:
  1. my-goods.vue 组件的 methods 节点中,定义 numChangeHandler 事件处理函数:

9.1.8 解决 NumberBox 数据不合法的问题

问题说明:当用户在 NumberBox 中输入字母等非法字符之后,会导致 NumberBox 数据紊乱的问题

  1. 打开项目根目录中 uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue 组件,修改 methods 节点中的 _onBlur 函数如下:
  1. 修改完毕之后,用户输入小数被转化为整数 ,用户输入非法字符被替换为默认值 1

9.1.9 完善 NumberBox 的 inputValue 侦听器

问题说明:在用户每次输入内容之后,都会触发 inputValue 侦听器,从而调用 this.$emit("change", newVal) 方法。这种做法可能会把不合法的内容传递出去!

  1. 打开项目根目录中 uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue 组件,修改 watch 节点中的 inputValue 侦听器如下:
  1. 修改完毕之后,NumberBox 组件只会把合法的、且不包含小数点的新值传递出去。

9.1.10 修改购物车中商品的数量

  1. store/cart.js 模块中,声明如下的 mutations 方法,用来修改对应商品的数量:
  1. cart.vue 页面中,通过 mapMutations 这个辅助函数,将需要的 mutations 方法映射到当前页面中使用:

9.1.11 渲染滑动删除的 UI 效果

滑动删除需要用到 uni-ui 的 uni-swipe-action 组件和 uni-swipe-action-item。详细的官方文档请参考SwipeAction 滑动操作。

效果如图:

  1. 改造 cart.vue 页面的 UI 结构,将商品列表区域的结构修改如下(可以使用 uSwipeAction 代码块快速生成基本的 UI 结构):
html 复制代码
<!-- 商品列表区域 -->
<!-- uni-swipe-action 是最外层包裹性质的容器 -->
<uni-swipe-action>
  <block v-for="(goods, i) in cart" :key="i">
    <!-- uni-swipe-action-item 可以为其子节点提供滑动操作的效果。需要通过 options 属性来指定操作按钮的配置信息 -->
    <uni-swipe-action-item :options="options" @click="swipeActionClickHandler(goods)">
      <my-goods :goods="goods" :show-radio="true" :show-num="true" @radio-change="radioChangeHandler" @num-change="numberChangeHandler"></my-goods>
    </uni-swipe-action-item>
  </block>
</uni-swipe-action>
  1. 在 data 节点中声明 options 数组,用来定义操作按钮的配置信息:
  1. methods 中声明 uni-swipe-action-item 组件的 @click 事件处理函数:
  1. 美化 my-goods.vue 组件的样式:

9.1.12 实现滑动删除的功能

  1. store/cart.js 模块的 mutations 节点中声明如下的方法,从而根据商品的 Id 从购物车中移除对应的商品:
  1. cart.vue 页面中,使用 mapMutations 辅助函数,把需要的方法映射到当前页面中使用:

9.2 收货地址区域

9.2.1 创建收货地址组件

  1. components 目录上鼠标右键,选择 新建组件,并填写组件相关的信息:
  1. 渲染收货地址组件的基本结构:
  1. 美化收货地址组件的样式:

9.2.2 实现收货地址区域的按需展示

  1. 在 data 中定义收货地址的信息对象:
  1. 使用 v-ifv-else 实现按需展示:

9.2.3 实现选择收货地址的功能

  1. 请选择收货地址+button 按钮绑定点击事件处理函数:
  1. 定义 chooseAddress 事件处理函数,调用小程序提供的 chooseAddress() API 实现选择收货地址的功能:
  1. 定义收货详细地址的计算属性:
  1. 渲染收货地址区域的数据:

9.2.4 将 address 信息存储到 vuex 中

  1. store 目录中,创建用户相关的 vuex 模块,命名为 user.js
  1. store/store.js 模块中,导入并挂载 user.js 模块:
  1. 改造 address.vue 组件中的代码,使用 vuex 提供的 address 计算属性 替代 data 中定义的本地 address 对象

修正:my-address.vue 52行那里少了个逗号。

9.2.5 将 Store 中的 address 持久化存储到本地

  1. 修改 store/user.js 模块中的代码如下:

9.2.6 将 addstr 抽离为 getters

目的:为了提高代码的复用性,可以把收货的详细地址抽离为 getters,方便在多个页面和组件之间实现复用。

  1. 剪切 my-address.vue 组件中的 addstr 计算属性的代码,粘贴到 user.js 模块中,作为一个 getters 节点:
  1. 改造 my-address.vue 组件中的代码,通过 mapGetters 辅助函数,将 m_user 模块中的 addstr 映射到当前组件中使用:

9.2.7 重新选择收货地址

  1. 为 class 类名为 address-info-box 的盒子绑定 click 事件处理函数如下:

9.2.8 解决收货地址授权失败的问题

如果在选择收货地址的时候,用户点击了取消授权 ,则需要进行特殊的处理 ,否则用户将无法再次选择收货地址

  1. 改造 chooseAddress 方法如下:
  1. methods 节点中声明 reAuth 方法如下:

9.2.9 解决 iPhone 真机上无法重新授权的问题

问题说明:在 iPhone 设备上,当用户取消授权之后,再次点击选择收货地址按钮的时候,无法弹出授权的提示框!

  1. 导致问题的原因 - 用户取消授权后,再次点击 "选择收货地址" 按钮的时候:

    • 模拟器安卓真机 上,错误消息 err.errMsg 的值为 chooseAddress:fail auth deny

    • iPhone 真机 上,错误消息 err.errMsg 的值为 chooseAddress:fail authorize no response

  2. 解决问题的方案 - 修改 chooseAddress 方法中的代码,进一步完善用户没有授权时的 if 判断条件即可:


9.3 结算区域

9.3.1 把结算区域封装为组件

  1. components 目录中,新建 my-settle 结算组件:
  1. 初始化 my-settle 组件的基本结构和样式:
  1. cart.vue 页面中使用自定义的 my-settle 组件,并美化页面样式,防止页面底部被覆盖:

9.3.2 渲染结算区域的结构和样式

  1. 定义如下的 UI 结构:
  1. 美化样式:

9.3.3 动态渲染已勾选商品的总数量

  1. store/cart.js 模块中,定义一个名称为 checkedCount 的 getters,用来统计已勾选商品的总数量:
  1. my-settle 组件中,通过 mapGetters 辅助函数,将需要的 getters 映射到当前组件中使用:
  1. checkedCount 的值渲染到页面中:

9.3.4 动态渲染全选按钮的选中状态

  1. 使用 mapGetters 辅助函数,将商品的总数量 映射到当前组件中使用,并定义一个叫做 isFullCheck 的计算属性:
  1. 为 radio 组件动态绑定 checked 属性的值:

9.3.5 实现商品的全选/反选功能

  1. store/cart.js 模块中,定义一个叫做 updateAllGoodsState 的 mutations 方法,用来修改所有商品的勾选状态:
  1. my-settle 组件中,通过 mapMutations 辅助函数,将需要的 mutations 方法映射到当前组件中使用:
  1. 为 UI 中的 label 组件绑定 click 事件处理函数:
  1. my-settle 组件的 methods 节点中,声明 changeAllState 事件处理函数:

9.3.6 动态渲染已勾选商品的总价格

  1. store/cart.js 模块中,定义一个叫做 checkedGoodsAmount 的 getters,用来统计已勾选商品的总价格:
  1. my-settle 组件中,使用 mapGetters 辅助函数,把需要的 checkedGoodsAmount 映射到当前组件中使用:
  1. 在组件的 UI 结构中,渲染已勾选的商品的总价:

9.3.7 动态计算购物车徽标的数值

  1. 问题说明:当修改购物车中商品的数量之后,tabBar 上的数字徽标不会自动更新。

  2. 解决方案 :改造 mixins/tabbar-badge.js 中的代码,使用 watch 侦听器,监听 total 总数量的变化,从而动态为 tabBar 的徽标赋值:


9.3.8 渲染购物车为空时的页面结构

  1. 资料 目录中的 cart_empty@2x.png 图片复制到项目的 /static/ 目录中

  2. 改造 cart.vue 页面的 UI 结构,使用 v-ifv-else 控制购物车区域空白购物车区域的按需展示:

  1. 美化空白购物车区域的样式:

9.4 分支的合并与提交

  1. cart 分支进行本地提交:
bash 复制代码
git add .
git commit -m "完成了购物车的开发"
  1. 将本地的 cart 分支推送到码云:
bash 复制代码
git push -u origin cart
  1. 将本地 cart 分支中的代码合并到 master 分支:
bash 复制代码
git checkout master
git merge cart
git push
  1. 删除本地的 cart 分支:
bash 复制代码
git branch -d cart
相关推荐
TuCoder3 小时前
景区导览小程序功能选型指南:刚需配置、增值功能与技术避坑要点
小程序
中犇科技5 小时前
2026商城APP开发公司 TOP5(电商垂直版)
uni-app
扁豆的主人5 小时前
Uniapp如何构建和部署
uni-app
小羊Yveesss6 小时前
2026年知识付费小程序多少钱一个?
小程序
hhzz6 小时前
Uniapp项目中解决一个比较典型的图标渲染问题:原生 tabBar(pages.json 里配置的那种)
uni-app·json
一只皮卡皮卡丘6 小时前
微信小程序tab页苹果显示安卓不显示的问题
微信小程序·小程序
六月的可乐6 小时前
【干货】小程序虚拟瀑布流探索小结
前端·react.js·小程序
鹤鸣的日常19 小时前
前端运行时动态环境变量方案
前端·react.js·docker·前端框架·vue·gitlab
小徐_233320 小时前
Wot UI 2.1.0 发布:ConfigProvider 全局配置能力升级
前端·uni-app