uni-app之旅-day07-购物车页面
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 9.1 商品列表区域
- 9.1.1 渲染购物车商品列表的标题区域
- 9.1.2 渲染商品列表区域的基本结构
- 9.1.3 为 my-goods 组件封装 radio 勾选状态
- 9.1.4 为 my-goods 组件封装 radio-change 事件
- 9.1.5 修改购物车中商品的勾选状态
- 9.1.6 为 my-goods 组件封装 NumberBox
- 9.1.7 为 my-goods 组件封装 num-change 事件
- 9.1.8 解决 NumberBox 数据不合法的问题
- 9.1.10 修改购物车中商品的数量
- 9.1.11 渲染滑动删除的 UI 效果
- 9.1.12 实现滑动删除的功能
9.1 商品列表区域
9.1.1 渲染购物车商品列表的标题区域
- 🍕🍕🍕 UI 结构
<view class="cart-title"><!-- 左侧图标 --><uni-icons type="shop" size="18"></uni-icons><!-- 描述文本 --><text class="cart-title-text">购物车</text></view>
- 样式
<style lang="scss">
.cart-title{height: 40px;display: flex;align-items: center;font-size: 14px;padding-left: 5px;border-bottom: 1px solid #efefef;.cart-title-text{margin-left: 10px;}
}
</style>
9.1.2 渲染商品列表区域的基本结构
- 通过 mapState 辅助函数,将 Store 中的 cart 数组映射到当前页面中使用
import badgeMix from '@/mixins/tabbar-badge.js'
// 按需导入 mapState 这个辅助函数
import { mapState } from 'vuex'export default {mixins: [badgeMix],computed: {// 将 m_cart 模块中的 cart 数组映射到当前页面中使用...mapState('m_cart', ['cart']),},data() {return {}},
}
- 在 UI 结构中,通过 v-for 指令循环渲染自定义的 my-goods 组件
<!-- 商品列表区域 -->
<block v-for="(goods, i) in cart" :key="i"><my-goods :goods="goods"></my-goods>
</block>
9.1.3 为 my-goods 组件封装 radio 勾选状态
<!-- 商品左侧图片区域 -->
<view class="goods-item-left"><radio checked color="#C00000"></radio><image :src="goods.goods_small_logo || defaultPic" class="goods-pic"></image>
</view>
- 给类名为 goods-item-left 的 view 组件添加样式,实现 radio 组件和 image 组件的左右布局
.goods-item-left {margin-right: 5px;display: flex;justify-content: space-between;align-items: center;.goods-pic {width: 100px;height: 100px;display: block;}
}
- 封装名称为 showRadio 的 props 属性,来控制当前组件中是否显示 radio 组件
export default {// 定义 props 属性,用来接收外界传递到当前组件的数据props: {// 商品的信息对象goods: {type: Object,default: {},},// 是否展示图片左侧的 radioshowRadio: {type: Boolean,// 如果外界没有指定 show-radio 属性的值,则默认不展示 radio 组件default: false,},},
}
- 使用 v-if 指令控制 radio 组件的按需展示
<!-- 商品左侧图片区域 -->
<view class="goods-item-left"><!-- 使用 v-if 指令控制 radio 组件的显示与隐藏 --><radio checked color="#C00000" v-if="showRadio"></radio><image :src="goods.goods_small_logo || defaultPic" class="goods-pic"></image>
</view>
- 在 cart.vue 页面中的商品列表区域,指定 :show-radio=“true” 属性,从而显示 radio 组件
<!-- 商品列表区域 -->
<block v-for="(goods, i) in cart" :key="i"><my-goods :goods="goods" :show-radio="true"></my-goods>
</block>
- 修改 my-goods.vue 组件,动态为 radio 绑定选中状态
<!-- 商品左侧图片区域 -->
<view class="goods-item-left"><!-- 存储在购物车中的商品,包含 goods_state 属性,表示商品的勾选状态 --><radio :checked="goods.goods_state" color="#C00000" v-if="showRadio"></radio><image :src="goods.goods_small_logo || defaultPic" class="goods-pic"></image>
</view>
9.1.4 为 my-goods 组件封装 radio-change 事件
- 当用户点击 radio 组件,希望修改当前商品的勾选状态,此时用户可以为 my-goods 组件绑定 @radio-change 事件,从而获取当前商品的 goods_id 和 goods_state
<!-- 商品列表区域 -->
<block v-for="(goods, i) in cart" :key="i"><!-- 在 radioChangeHandler 事件处理函数中,通过事件对象 e,得到商品的 goods_id 和 goods_state --><my-goods :goods="goods" :show-radio="true" @radio-change="radioChangeHandler"></my-goods>
</block>
- 定义 radioChangeHandler 事件处理函数
methods: {// 商品的勾选状态发生了变化radioChangeHandler(e) {console.log(e) // 输出得到的数据 -> {goods_id: 395, goods_state: false}}
}
- 在 my-goods.vue 组件中,为 radio 组件绑定 @click 事件处理函数
<!-- 商品左侧图片区域 -->
<view class="goods-item-left"><radio :checked="goods.goods_state" color="#C00000" v-if="showRadio" @click="radioClickHandler"></radio><image :src="goods.goods_small_logo || defaultPic" class="goods-pic"></image>
</view>
- 在 my-goods.vue 组件的 methods 节点中,定义 radioClickHandler 事件处理函数
methods: {// radio 组件的点击事件处理函数radioClickHandler() {// 通过 this.$emit() 触发外界通过 @ 绑定的 radio-change 事件,// 同时把商品的 Id 和 勾选状态 作为参数传递给 radio-change 事件处理函数this.$emit('radio-change', {// 商品的 Idgoods_id: this.goods.goods_id,// 商品最新的勾选状态goods_state: !this.goods.goods_state})}
}
9.1.5 修改购物车中商品的勾选状态
- 在 store/cart.js 模块中,声明如下的 mutations 方法,用来修改对应商品的勾选状态
// 更新购物车中商品的勾选状态
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')}
}
- 🍳🥟🍳在 cart.vue 页面中,导入 mapMutations 这个辅助函数,从而将需要的 mutations 方法映射到当前页面中使用
import badgeMix from '@/mixins/tabbar-badge.js'
import { mapState, mapMutations } from 'vuex'export default {mixins: [badgeMix],computed: {...mapState('m_cart', ['cart']),},data() {return {}},methods: {...mapMutations('m_cart', ['updateGoodsState']),// 商品的勾选状态发生了变化radioChangeHandler(e) {this.updateGoodsState(e)},},
}
9.1.6 为 my-goods 组件封装 NumberBox
- 注意:NumberBox 组件是 uni-ui 提供的
- 修改 my-goods.vue 组件的源代码,在类名为 goods-info-box 的 view 组件内部渲染 NumberBox 组件的基本结构
<view class="goods-info-box"><!-- 商品价格 --><view class="goods-price">¥{{goods.goods_price | tofixed}}</view><!-- 商品数量 --><uni-number-box :min="1"></uni-number-box>
</view>
- 样式
.goods-item-right {display: flex;flex: 1;flex-direction: column;justify-content: space-between;.goods-name {font-size: 13px;}.goods-info-box {display: flex;align-items: center;justify-content: space-between;}.goods-price {font-size: 16px;color: #c00000;}
}
- 在 my-goods.vue 组件中,动态为 NumberBox 组件绑定商品的数量值
<view class="goods-info-box"><!-- 商品价格 --><view class="goods-price">¥{{goods.goods_price | tofixed}}</view><!-- 商品数量 --><uni-number-box :min="1" :value="goods.goods_count"></uni-number-box>
</view>
- 在 my-goods.vue 组件中,封装名称为 showNum 的 props 属性,来控制当前组件中是否显示 NumberBox 组件
export default {// 定义 props 属性,用来接收外界传递到当前组件的数据props: {// 商品的信息对象goods: {type: Object,defaul: {},},// 是否展示图片左侧的 radioshowRadio: {type: Boolean,// 如果外界没有指定 show-radio 属性的值,则默认不展示 radio 组件default: false,},// 是否展示价格右侧的 NumberBox 组件showNum: {type: Boolean,default: false,},},
}
- 在 my-goods.vue 组件中,使用 v-if 指令控制 NumberBox 组件的按需展示
<view class="goods-info-box"><!-- 商品价格 --><view class="goods-price">¥{{goods.goods_price | tofixed}}</view><!-- 商品数量 --><uni-number-box :min="1" :value="goods.goods_count" @change="numChangeHandler" v-if="showNum"></uni-number-box>
</view>
- 在 cart.vue 页面中的商品列表区域,指定 :show-num=“true” 自定义属性,从而显示 NumberBox 组件
<!-- 商品列表区域 -->
<block v-for="(goods, i) in cart" :key="i"><my-goods :goods="goods" :show-radio="true" :show-num="true" @radio-change="radioChangeHandler"></my-goods>
</block>
9.1.7 为 my-goods 组件封装 num-change 事件
- 当用户修改了 NumberBox 的值以后,希望将最新的商品数量更新到购物车中,此时需要为 my-goods 组件绑定 @num-change 自定义事件,获取当前商品的 goods_id 和 goods_count
<!-- 商品列表区域 -->
<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 事件处理函数
// 商品的数量发生了变化
numberChangeHandler(e) {console.log(e)
}
- 在 my-goods.vue 组件中,为 uni-number-box 组件绑定 @change 事件处理函数
<uni-number-box :min="1" :value="goods.goods_count" @change="numChangeHandler" v-if="showNum"></uni-number-box>
- 在 my-goods.vue 组件的 methods 节点中,定义 numChangeHandler 事件处理函数
methods: {// NumberBox 组件的 change 事件处理函数numChangeHandler(val) {// 通过 this.$emit('事件名',{需要传的数据}) 触发外界通过 @ 绑定的 num-change 自定义事件this.$emit('num-change', {// 商品的 Idgoods_id: this.goods.goods_id,// 商品的最新数量goods_count: +val})}
}
9.1.8 解决 NumberBox 数据不合法的问题
- 当用户在 NumberBox 中输入字母等非法字符之后,会导致 NumberBox 数据紊乱的问题
- 打开项目根目录中 uni_modules/uni-number-box/components//uni-number-box/uni-number-box.vue 组件,修改 methods 节点中的 _onBlur 函数
_onBlur(event) {// 官方的代码没有进行数值转换,用户输入的 value 值可能是非法字符:// let value = event.detail.value;// 将用户输入的内容转化为整数let value = parseInt(event.detail.value);if (!value) {// 如果转化之后的结果为 NaN,则给定默认值为 1this.inputValue = 1;return;}// 省略其它代码...
}
- 修改完毕之后,用户输入小数会被转化为整数,用户输入非法字符会被替换为默认值 1
9.1.10 修改购物车中商品的数量
- 在 store/cart.js 模块中,声明如下的 mutations 方法
// 更新购物车中商品的数量
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')}
}
- 在 cart.vue 页面中,通过 mapMutations 这个辅助函数,将需要的 mutations 方法映射到当前页面中使用
import { mapState, mapMutations } from 'vuex'
export default {mixins: [badgeMix],computed: {...mapState('m_cart', ['cart']),},data() {return {}},methods: {...mapMutations('m_cart', ['updateGoodsState', 'updateGoodsCount']),// 商品的勾选状态发生了变化radioChangeHandler(e) {this.updateGoodsState(e)},// 商品的数量发生了变化numberChangeHandler(e) {this.updateGoodsCount(e)},},
}
9.1.11 渲染滑动删除的 UI 效果
- 🍔🍔🍔滑动删除需要用到 uni-ui 的 uni-swipe-action 组件和 uni-swipe-action-item。详细的请参考SwipeAction 滑动操作官方文档
- 改造 cart.vue 页面的 UI 结构,将商品列表区域的结构修改如下
<uni-swipe-action><block v-for="(goods, i) in cart" :key="i"><!-- uni-swipe-action-item 可以为其子节点提供滑动操作的效果。需要通过 options 属性来指定操作按钮的配置信息 --><uni-swipe-action-item :right-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>
- 在 data 节点中声明 options 数组,用来定义操作按钮的配置信息
data(){return{options:[{text:'删除',style:{backgroundColor:'#C00000'}} ] }
}
- 在 methods 中声明 uni-swipe-action-item 组件的 @click 事件处理函数
methods:{// 点击了滑动操作按钮
swipeActionClickHandler(goods) {console.log(goods)
}
}
- 美化 my-goods.vue 组件的样式
.goods-item {// 让 goods-item 项占满整个屏幕的宽度width: 750rpx;// 设置盒模型为 border-boxbox-sizing: border-box;display: flex;padding: 10px 5px;border-bottom: 1px solid #f0f0f0;
}
9.1.12 实现滑动删除的功能
- 🥟🥟🥟在 store/cart.js 模块的 mutations 节点中声明如下的方法,从而根据商品的 Id 从购物车中移除对应的商品
//根据id从购物车中删除对应的商品信息removeGoodsById(state,goods_id){// 调用数组的 filter 方法进行过滤,重新赋值(剩下的商品)state.cart = state.cart.filter(x=>x.goods_id !== goods_id)//持久化存储本地this.commit('m_cart/saveToStorage')}
- 在 cart.vue 页面中,使用 mapMutations 辅助函数,把需要的方法映射到当前页面中使用
methods: {...mapMutations('m_cart', ['updateGoodsState', 'updateGoodsCount', 'removeGoodsById']),// 商品的勾选状态发生了变化radioChangeHandler(e) {this.updateGoodsState(e)},// 商品的数量发生了变化numberChangeHandler(e) {this.updateGoodsCount(e)},// 点击了滑动操作按钮swipeActionClickHandler(goods) {this.removeGoodsById(goods.goods_id)}
}
相关文章:
uni-app之旅-day07-购物车页面
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 9.1 商品列表区域9.1.1 渲染购物车商品列表的标题区域9.1.2 渲染商品列表区域的基本结构9.1.3 为 my-goods 组件封装 radio 勾选状态9.1.4 为 my-goods 组件封装 ra…...

【机器学习】并行计算(parallel computation)Part2
Asynchronous Parallel Gradient Descent Using Parameter Server 用Parameter Server实现异步并行梯度下降 Parameter Server这种编程模型可以实现异步并行梯度下降,架构采用的是Client-Server,通信方式是Message-passing,同步方式是异步的…...
AI学习指南深度学习篇-迁移学习的应用场景
AI学习指南深度学习篇 - 迁移学习的应用场景 引言 迁移学习(Transfer Learning)是一种强有力的技术,尤其在深度学习领域的应用越来越广泛。通过在一个领域学到的知识来帮助另一个领域的学习,迁移学习尤其适用于数据稀缺的场景。…...

【web前端设计】jquery图标动画特效
学习目标 学习web前端设计技术(HTML、css、JavaScript、jQuery等),综合运用技术,将其与HTML元素结合,设计样式、监听事件、添加动画等,给用户呈现出更好的视觉交互效果。本文主要学习分页按钮自动放大、元…...

Linux——用户/用户组
创建用户组groupadd groupadd 用户组 删除用户组groupdel groupdel 用户组 创建用户useradd useradd 用户名 - g 用户组 useradd 用户名 -d HOME路径 删除用户userdel userdel 用户 userdel -r 用户 (删除用户的 HOME 目录,不使用 -r ࿰…...
HDFS上传下载命令
hadoop <组件> -<操作> /path1/test.txt / path2 上传:hadoop fs -put /path1/test.txt / path2 下载:hadoop fs -get /path2/test.txt / path3 查看目录:hadoop fs -ls / 查看文件:hadoop fs -cat / path…...

Nodejs使用http模块创建Web服务器接收解析RFID读卡器刷卡数据
本示例使用设备: https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.1d292c1buHvw58&ftt&id22173428704 Javascript源码 //引用http模块创建web服务器,监听指定的端口获取以GET、POST、JSON等方式上传的数据,并回应驱动读卡…...

基于python的《C语言程序设计》课程成绩分析
作者:Svan.声明:未经本人允许,不得对本文中的任何内容、数据进行转载,本人(作者)已经对本文内容申请撰写了论文,随意转载使用本文任何内容的,要追究其法律责任!!…...
@Component 和 @Bean 的区别与联系
相同点: Component 和 Bean 是两种使用注解来定义bean的方式。 Component和Bean的目的是一样的,都是注册bean到Spring容器中。 两者都可以通过Autowired装配 不同点: Component 和 它的子类型(Controller, Service and Reposit…...

高手炒现货黄金短线的方法
现货黄金短线交易的精髓在于“计划你的交易”。短线交易不是临时起意的赌博,也不是盘口随意的追涨杀跌,而是所有因素分析以后的结果。新手进行短线操作容易流为频繁的随意操作,导致成功率不高。但当投资者有了准备,短线交易就再也…...

后端:唯一ID有哪些生成方式
文章目录 在后端开发中的ID生成策略1. 数字型 ID特点:优点:缺点:例子:常见用法: 2. UUID(通用唯一标识符)特点:优点:缺点:例子:常见用法ÿ…...

LabVIEW提高开发效率技巧----高精度延时
在LabVIEW开发中,时间控制是许多应用中的关键环节,尤其是高精度应用中,时钟漂移会严重影响程序的准确性。为此,使用Wait Until Next ms Multiple来代替简单的Wait (ms),可以显著减少时钟漂移,确保高精度延时…...
<Link><Link> 和 <a> </a>标签的区别
1. Link (React Router): 作用: Link 是 react-router-dom 提供的组件,用于在 React 应用中创建前端路由跳转。它不会导致页面重新加载。优点: 无刷新跳转: 使用 Link 进行导航时,React 的路由器会捕获并处理链接,避免浏览器的全…...

靶场战神为何会陨落?
我从第一个SQL注入漏洞原理学起,从sql-libas到DVWA,到pikachu再到breach系列,DC系列靶场,再到实战挖洞,发现靶场与实战的区别是极其大的。 我个人觉得在这种web环境下,难的不是怎么测一个漏洞点,而是怎么找一个漏洞点。靶场与实战最大的区别在于你不知道这个地方到底有没有漏洞…...

rpm 命令
rpm(Red Hat Package Manager)是 Red Hat Linux 及其衍生发行版(如 CentOS、Fedora)中用于管理软件包的系统。它允许用户安装、卸载、升级、查询和验证软件包。 一、安装软件包 (1)安装一个 RPM 软件包&a…...

录微课专用提词器,不会被录进视频中的提词器,还能显示PPT中备注的内容
不坑提词器,全称:不坑隐形提词器。是一款能够在截图、录屏、直播过程中隐藏界面的提词器软件。 系统要求:Win10 1024 以上(特别提醒:Win7状态下不可隐身) ⏬下载 提词器默认放在不坑盒子的安装目录下&…...

Ansible概述
目录 一、ansible简介 二、absible的特点 三、ansible的工作原理以及流程 四、ansible环境安装部署 五、ansible命令行模块 六、inventory 主机清单 一、ansible简介 Ansible是一个基于Python开发的配置管理和应用部署工具,现在也在自动化管理领域大放异彩。…...

NTC 温度电阻计算方式
100K温度值列表 https://wenku.baidu.com/view/59565cba1a37f111f1855b38?aggId989bc39968d97f192279168884868762cbaebb44&frcatalogMain_text_ernie_recall_feed_index%3Awk_recommend_main1&wkts1729568234531&bdQuery100K%E6%B8%A9%E5%BA%A6%E7%94%B5%E9%98%B…...
Qt中自定义qDebug打印信息的宏(文件名,行数,函数名,日期,时间等前缀)并取消打印
使用qDebug()打印信息时,默认打印"<<"符号后面的信息。 通过自定义宏,可以额外打印文件名,行数,函数,日期、时间等前缀,方便快速定位调式信息的位置。 同时,可以定义宏取消打…...

【基于docker的深度学习训练环境】关键步骤记录
最近给公司搭建了一个小型的深度学习环境,实现了多人通过SSH对GPU资源的利用,下面对一些关键架构和易用性部分进行记录。 一、整体软硬件框架 1、硬件配置,采用的双GPU的方案,两块消费级显卡。 2、应用层架构 宿主机系统为ubunt…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...