HarmonyOS NEXT星河版之美团外卖点餐功能实战(下)

文章目录

    • 一、购物车逻辑
      • 1.1 购物车及加减菜
      • 1.2 菜品的加减---方案一
      • 1.3 菜品的加减---方案二
      • 1.4 购物车View完善
      • 1.5 清空购物车
      • 1.5 购物车数量和价格
    • 二、小结

一、购物车逻辑

1.1 购物车及加减菜

utils目录下新建CartStore.ets文件,如下:

import { FoodItem } from '../models'// 本地持久化购物车数据
PersistentStorage.persistProp<FoodItem[]>('cartStore', [])export class CartStore {static getCarts() {return AppStorage.get<FoodItem[]>('cartStore') || [] as FoodItem[]}/*** 加菜or减菜* @param foodItem* @param type*/static addOrCutFood(foodItem: FoodItem, type: 'add' | 'cut') {const cartList = CartStore.getCarts()const item = cartList.find((item) => item.id === foodItem.id)// 加菜if (type === 'add') {if (item) {item.count++} else {foodItem.count = 1cartList.unshift(foodItem)}} else { // 减菜if (item && item.count > 0) {item.count--if (item.count === 0) {const index = cartList.findIndex((item) => item.id === foodItem.id)cartList.splice(index, 1)}}}AppStorage.set<FoodItem[]>('cartStore', [...cartList])}
}

1.2 菜品的加减—方案一

实现如下效果,当选择数量大于0时展示-及数量
在这里插入图片描述
改造MTAddCutView,如下:

import { FoodItem } from '../models'
import { CartStore } from '../utils/CartStore'@Preview
@Component
export struct MTAddCutView {// 当前菜品@Require @Prop foodItem: FoodItem = new FoodItem()// 购物车数据@Consume cartList: FoodItem[]// 当前选择数量getCount() {return this.cartList.find(obj => obj.id === this.foodItem.id)?.count || 0}build() {Row({ space: 8 }) {Row() {Image($r('app.media.ic_screenshot_line')).width(10).aspectRatio(1)}.width(16).height(16).justifyContent(FlexAlign.Center).backgroundColor(Color.White).borderRadius(4).border({color: $r('app.color.main_color'),width: 0.5})// 如果为0,则取消展示.visibility(this.getCount() > 0 ? Visibility.Visible : Visibility.Hidden)// 减少菜品.onClick(() => {CartStore.addOrCutFood(this.foodItem, 'cut')})Text(this.getCount().toString()).fontSize(14).visibility(this.getCount() > 0 ? Visibility.Visible : Visibility.Hidden)Row() {Image($r('app.media.ic_public_add_filled')).width(10).aspectRatio(1)}.width(16).height(16).justifyContent(FlexAlign.Center).borderRadius(4).backgroundColor($r('app.color.main_color'))// 添加菜品.onClick(() => {CartStore.addOrCutFood(this.foodItem, 'add')})}}
}

在主页面MeiTuanPage.ets中,通过WatchStorageProp实现数据动态展示:

// 方案一:使用StorageProp和Watch实现
@StorageProp('cartStore') @Watch('onCartChange') cartData: FoodItem[] = []
// 购物车数据变化发生回调
onCartChange() {this.cartList = CartStore.getCarts()
}

1.3 菜品的加减—方案二

使用事件总线实现事件的发布和订阅。
CartStore.ets中增加事件发布:

...AppStorage.set<FoodItem[]>('cartStore', [...cartList])
// 方案二:使用事件总线
getContext().eventHub.emit('changeCart')
...

MeiTuanPage.ets中注册订阅:

aboutToAppear(): void {this.categoryList = mockCategorythis.cartList = CartStore.getCarts()// 方案二:使用事件总线getContext().eventHub.on('changeCart', () => {this.cartList = CartStore.getCarts()})
}

1.4 购物车View完善

购物车展示真实数据及加减菜品:
MTCartView

import { FoodItem } from '../models'
import { MTCartItemView } from './MTCartItemView'@Preview
@Component
export struct MTCartView {@Consume cartList: FoodItem[]build() {Column() {Column() {// 头部Row() {Text('购物车').fontSize(14)Text('清空购物车').fontColor($r('app.color.search_font_color')).fontSize(12)}.width('100%').height(48).justifyContent(FlexAlign.SpaceBetween).padding({ left: 15, right: 15 })// 购物车列表List() {ForEach(this.cartList, (item: FoodItem) => {ListItem() {MTCartItemView({ foodItem: item })}})}.divider({ strokeWidth: 1, color: '#e5e5e5', startMargin: 20, endMargin: 20 })}.backgroundColor(Color.White).padding({bottom: 88}).borderRadius({topLeft: 12,topRight: 12})}.width('100%').height('100%').justifyContent(FlexAlign.End).backgroundColor('rgba(0,0,0,0.5)')}
}

MTCartItemView

import { FoodItem } from '../models'
import { MTAddCutView } from './MTAddCutView'@Preview
@Component
export struct MTCartItemView {foodItem: FoodItem = new FoodItem()build() {Row({ space: 6 }) {Image('https://bkimg.cdn.bcebos.com/pic/4d086e061d950a7bc94a331704d162d9f3d3c9e2').width(42).aspectRatio(1).borderRadius(5)Column({ space: 3 }) {Text(this.foodItem.name)Row() {Text() {Span('¥').fontSize(10)Span(this.foodItem.price.toString()).fontColor($r('app.color.main_color')).fontSize(14).fontWeight(600)}MTAddCutView({ foodItem: this.foodItem })}.width('100%').justifyContent(FlexAlign.SpaceBetween)}.layoutWeight(1).alignItems(HorizontalAlign.Start)}.height(60).alignItems(VerticalAlign.Top).width('100%').padding({ top: 12, left: 15, right: 15, bottom: 12 })}
}

1.5 清空购物车

CartStore.ets中增加清空方法:

static clearCart() {AppStorage.set('cartStore', [])getContext().eventHub.emit('changeCart')
}

购物车View中增加点击事件:

...
Text('清空购物车').fontColor($r('app.color.search_font_color')).fontSize(12).onClick(() => {CartStore.clearCart()})
...

1.5 购物车数量和价格

在这里插入图片描述

修改MTBottomView,计算购物车数量和价格:

import { FoodItem } from '../models'@Component
export struct MTBottomView {@ConsumeshowCart: boolean@Consume cartList: FoodItem[]// 获取总数量getTotalCount() {return this.cartList.reduce((pre: number, item: FoodItem) => {return pre + item.count}, 0)}// 获取总价格getTotalPrice() {return this.cartList.reduce((pre: number, item: FoodItem) => {return pre + item.count * item.price}, 0)}build() {Row() {// 小哥+角标Badge({ value: this.getTotalCount().toString(), style: { badgeSize: 18 }, position: BadgePosition.Right }) {Image($r('app.media.ic_public_cart')).height(69).width(47).position({y: -20})}.margin({ left: 28, right: 12 }).onClick(() => {this.showCart = !this.showCart})// 金额+描述Column() {Text() {Span('¥').fontColor(Color.White).fontSize(12)Span(this.getTotalPrice().toString()).fontColor(Color.White).fontSize(25)}Text('预估另需配送费¥5').fontColor($r('app.color.search_font_color')).fontSize(12)}.alignItems(HorizontalAlign.Start).layoutWeight(1)// 去结算Text('去结算').width(80).height(50).fontSize(16).backgroundColor($r('app.color.main_color')).textAlign(TextAlign.Center).borderRadius({topRight: 25,bottomRight: 25})}.height(50).width('88%').margin({ bottom: 20 }).backgroundColor(Color.Black).borderRadius(26)}
}

二、小结

  • cartStore应用
  • 加减菜逻辑
  • 购物车逻辑
  • 事件总线

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/10106.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3的CRUD模版(附Demo)

目录 前言模版 前言 用惯Vue2之后&#xff0c;在碰Vue3后&#xff0c;整体还是有所区别 此文主要做一个回顾总结 假设界面如下&#xff1a; 可CRUD&#xff0c;对应的新增 添加一些必选项&#xff1a; 其中数据库的设计如下&#xff1a; 模版 对应需要注意参数位置、初始…

(41)5.6-5.8数据结构(栈和队列的应用和数组)

1.栈在括号匹配中的应用 #define _CRT_SECURE_NO_WARNINGS #define MaxSize 10 typedef struct { char data[MaxSize];//静态数组存放栈中元素 int top; //栈顶指针 }SqStack;//初始化栈 void InitStack(SqStack& S);//判断栈是否为空 bool StackEmpty(SqStack S…

Feign 第一次调用为什么会很慢?

feign调用的大致过程&#xff1f; Feign进行远程调用的&#xff0c;这里面包括&#xff0c;注册中心、负载均衡、FeignClient之间的关系&#xff0c;微服务通过不论是eureka、nacos也好注册到服务端&#xff0c;Feign是靠Ribbon做负载的&#xff0c;而Ribbon需要拿到注册中心的…

从零开始构建现代深度学习框架:数据支持、网站链接与代码步骤

文章目录 一、数据支持二、网站链接三、代码步骤1. 导入必要的库和模块2. 加载和预处理数据&#xff08;以MNIST为例&#xff09;3. 定义模型结构4. 编译模型5. 训练模型6. 评估模型 一、数据支持 在构建深度学习框架的过程中&#xff0c;数据是不可或缺的。以下是一些可能用到…

android进阶-Binder

参考&#xff1a;Android——Binder机制-CSDN博客 机制&#xff1a;Binder是一种进程间通信的机制 驱动&#xff1a;Binder是一个虚拟物理设备驱动 应用层&#xff1a;Binder是一个能发起进程间通信的JAVA类 Binder相对于传统的Socket方式&#xff0c;更加高效Binder数据拷贝…

豆芽机置入语音芯片WTN6040-8S:开启智能生活新篇章,让豆芽制作更便捷有趣

豆芽机的开发背景&#xff1a; 豆芽作为一种营养丰富、味道鲜美的食品&#xff0c;深受广大消费者的喜爱。然而&#xff0c;传统的豆芽生产过程繁琐&#xff0c;需要耗费大量的时间和人力&#xff0c;且存在生产效率低、质量不稳定等问题。随着人们生活节奏的加快和对健康饮食的…

DataLab-数据分析的Ai辅助工具

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;DataLab是一个由DataCamp提供的强大在线数据分析平台&#xff0c;它通过AI技术简化了数据处理流程&#xff0c;使得用户无需编程或数据分析的高级技能即可快速获取数据洞察。它支持多种数据源&#xff0c;包…

C++多态实现原理详解

阅读引言&#xff1a; 我想象了一下&#xff0c; 假如人有突然问我什么是多态&#xff0c; 我该如何给别人说清楚呢&#xff1f;所以写下这篇文章&#xff0c; 希望大家看完有所收获。 ①. 开胃小菜 先看这样一个开胃小菜 这里我有点小小的疑惑&#xff0c; 大小为啥是1。 在C…

Python | Leetcode Python题解之第74题搜索二维矩阵

题目&#xff1a; 题解&#xff1a; class Solution:def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:row,col len(matrix),len(matrix[0])row_l,row_r 0,row-1while row_l < row_r:m (row_lrow_r)//2if target < matrix[m][0]:row_r m-1…

使用 Docker 部署 VS Code in The Browser

1&#xff09;介绍 GitHub&#xff1a;https://github.com/coder/code-server 在日常学习工作中&#xff0c;Vscode 已成为我们首选的代码编辑器。然而&#xff0c;其局限性在于当我们从家到公司移动时&#xff0c;难以保持连续的编码体验。针对这一痛点&#xff0c;虽然市面上…

oracle 数据库与服务、实例与SID、表空间、用户与表模式

一、数据库与数据库服务: 概念:就是一个数据库的标识,在安装时就要想好,以后一般不修改,修改起来也麻烦,因为数据库一旦安装,数据库名就写进了控制文件,数据库表,很多地方都会用到这个数据库名。是数据库系统的入口,它会内置一些高级权限的用户如SYS,SYSTEM等。我们…

11.买卖股票的最佳时机Ⅰ

文章目录 题目简介题目解答解法一&#xff1a;一次遍历代码&#xff1a;复杂度分析&#xff1a; 题目链接 大家好&#xff0c;我是晓星航。今天为大家带来的是 买卖股票的最佳时机面试题Ⅰ 相关的讲解&#xff01;&#x1f600; 题目简介 题目解答 解法一&#xff1a;一次遍历…

怎么把手机ip地址变成了外省

在日常使用中&#xff0c;有时我们可能因为某些原因需要快速切换手机的IP地址&#xff0c;特别是当需要从一个省份切换到另一个省份的IP时。这种需求可能来源于网络访问限制、地理位置相关服务的使用、或者网络安全等方面的考虑。那么&#xff0c;怎么把手机IP地址变成外省呢&a…

Adobe Premiere Pro v24.3.0 解锁版 (领先的视频编辑软件)

前言 Adobe Premiere Pro&#xff08;简称PR&#xff09;是一款知名的专业视频编辑软件&#xff0c;数字视频剪辑软件。主要用来编辑视频和音频&#xff0c;可以在RGB和YUV色彩空间中以高达32位色彩的视频分辨率对4K和更高质量的视频文件进行编辑&#xff0c;支持VST音频插件和…

C++ 搜索二叉树

目录 1.二叉搜索树概念 2. 实现二叉搜索树 2.1. 二叉搜索树的插入 2.2查找 2.3删除节点 3.二叉树的应用&#xff08;KV结构&#xff09; 1.二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为…

Web界面加持!数据库备份神器,助你轻松备份数据!

使用这款带有Web界面的数据库备份神器&#xff0c;你可以轻松设置定时备份&#xff0c;确保数据安全无忧。备份结果即时通知&#xff0c;让你随时掌握备份状态。备份完成后&#xff0c;你将收到备份结果通知。无论是成功备份还是出现错误&#xff0c;你都能及时了解备份情况&am…

自适应熔断限流揭秘

原创 Chasen 拍码场 前言 自适应熔断与限流是在分布式系统中常用的机制&#xff0c;用于保护系统免受服务雪崩效应与突发流量影响。它能够根据系统的负载情况和性能指标自动调整限流策略&#xff0c;以确保系统能提供稳定可靠的服务&#xff0c;目前在业内已经有了不少的探索…

代码无界,创新无限!华为云开发者日 · 广州站来了!

5月23日&#xff0c;2024年首场华为云开发者日HDC.Cloud Day将在广州盛大举行。这场技术派对将为开发者们带来一场无与伦比的技术盛宴。在这里&#xff0c;开发者们将有机会现场聆听行业专家的精彩分享&#xff0c;深度了解众多前沿产品的最新技术和功能&#xff0c;并与行业专…

Sass语法介绍-运算

04 【Sass语法介绍-运算】 1.前言 运算是一种通过已知量可能的组合&#xff0c;获得新的量的行为。Sass 中也为我们提供了各种各样的运算&#xff0c;以便我们更好的处理样式代码。本节我们将学习 Sass 中的数字运算、关系运算、除法运算、颜色运算、字符串运算等等… 2.什么…

OSPF虚链路

原理概述 通常情况下&#xff0c;一个OSPF网络的每个非骨干区域都必须与骨干区域通过ABR路由器直接连接&#xff0c;非骨干区域之间的通信都需要通过骨干区域进行中转。但在现实中&#xff0c;可能会因为各种条件限制&#xff0c;导致非骨干区域和骨干区域无法直接连接&#x…