react + redux 之 美团案例
1.案例展示


2.环境搭建
- 克隆项目到本地(内置了基础静态组件和模版)
git clone http://git.itcast.cn/heimaqianduan/redux-meituan.git
- 安装所有依赖
npm i
- 启动mock服务(内置了json-server)
npm run serve
- 启动前端服务
npm run start
3.分类和商品列表渲染

1.store modules 下 takeaway.js文件
// 编写store
import { createSlice } from "@reduxjs/toolkit"
import axios from "axios"const foodsStore = createSlice({name: 'foods',initialState: {// 商品列表foodsList: [],a},reducers: {// 更改商品列表setFoodsList (state, action) {state.foodsList = action.payload}}
})// 异步获取部分
const { setFoodsList} = foodsStore.actions
const fetchFoodsList = () => {return async (dispatch) => {// 编写异步逻辑const res = await axios.get('http://localhost:3004/takeaway')// 调用dispatch函数提交actiondispatch(setFoodsList(res.data))}
}export { fetchFoodsList }const reducer = foodsStore.reducer
export default reducer
2.store下index.js文件
import foodsReducer from './modules/takeaway'
import { configureStore } from '@reduxjs/toolkit'
const store = configureStore({reducer: {foods: foodsReducer}
})
export default store
3.app.js
import { useDispatch, useSelector } from 'react-redux'
import { fetchFoodsList } from './store/modules/takeaway'
import { useEffect } from 'react'
// 触发action执行// 1. useDispatch -> dispatch 2. actionCreater导入进来 3.useEffectconst dispatch = useDispatch()useEffect(() => {dispatch(fetchFoodsList())}, [dispatch])// 获取foodsList渲染数据列表// 1. useSelectorconst { foodsList } = useSelector(state => state.foods){/* 外卖商品列表 */}{foodsList.map((item, index) => {return (<FoodsCategorykey={item.tag}// 列表标题name={item.name}// 列表商品foods={item.foods}/>)})}
4.menu.js
import { useDispatch,useSelector } from 'react-redux'
const dispatch = useDispatch()
const {foodsList} = useSelector(state=>state.foods)
5.index.js
// 注入store
import { Provider } from 'react-redux'
import store from './store'
const root = createRoot(document.getElementById('root'))
root.render(<Provider store={store}><App /></Provider>
)
4.点击分类激活实现

1.store modules下 takeaway.js文件
// 编写store
import { createSlice } from "@reduxjs/toolkit"
import axios from "axios"
const foodsStore = createSlice({name: 'foods',initialState: {// 商品列表foodsList: [],//激活indexactiveIndex:0,},reducers: {// 更改商品列表setFoodsList (state, action) {state.foodsList = action.payload},//更改activeIndexchangeActiveIndex(state,action){state.activeIndex = action.payload}}
})// 异步获取部分
const { setFoodsList,changeActiveIndex} = foodsStore.actions
2.menu.js
import classNames from 'classnames'
import './index.scss'import { useDispatch,useSelector } from 'react-redux'
import { changeActiveIndex} from '../../store/modules/takeaway'
const Menu = () => {const dispatch = useDispatch()const {foodsList,activeIndex} = useSelector(state=>state.foods) const menus = foodsList.map(item => ({ tag: item.tag, name: item.name }))return (<nav className="list-menu">{/* 添加active类名会变成激活状态 */}{menus.map((item, index) => {return (<divonClick={() => dispatch(changeActiveIndex(index))}key={item.tag}className={classNames('list-menu-item',activeIndex === index && 'active')}>{item.name}</div>)})}</nav>)
}export default Menu
3.app.js
const { foodsList , activeIndex} = useSelector(state => state.foods)
<div className="goods-list">{/* 外卖商品列表 */}{foodsList.map((item, index) => {return (activeIndex==index && <FoodsCategorykey={item.tag}// 列表标题name={item.name}// 列表商品foods={item.foods}/>)})}</div>
5.添加购物车

1.takeaway.js
// 编写storeimport { createSlice } from "@reduxjs/toolkit"
import axios from "axios"const foodsStore = createSlice({name: 'foods',initialState: {// 商品列表foodsList: [],// 菜单激活下标值activeIndex: 0,// 购物车列表cartList: []},reducers: {// 更改商品列表setFoodsList (state, action) {state.foodsList = action.payload},// 更改activeIndexchangeActiveIndex (state, action) {state.activeIndex = action.payload},// 添加购物车addCart (state, action) {// 是否添加过?以action.payload.id去cartList中匹配 匹配到了 添加过const item = state.cartList.find(item => item.id === action.payload.id)if (item) {item.count++} else {state.cartList.push(action.payload)}},}
})const { setFoodsList, changeActiveIndex, addCart} = foodsStore.actions
export { fetchFoodsList, changeActiveIndex, addCart}
2.foodItem下index.js文件
import { useDispatch } from 'react-redux'
import { setCarlist } from '../../../store/modules/takeaway'
const dispatch = useDispatch()<div className="goods-count"><span className="plus" onClick={() => dispatch(setCarlist({id,picture,name,unit,description,food_tag_list,month_saled,like_ratio_desc,price,tag,count}))}></span></div>
6.统计区域功能实现


1.cart下面index.js
import classNames from 'classnames'
import { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import Count from '../Count'
import './index.scss'const Cart = () => {const { carList } = useSelector(state => state.foods)// 计算总价 const totalPrice = carList.reduce((a, c) => a + c.price * c.count, 0)return (<div className="cartContainer"><div className="cart">{/* fill 添加fill类名购物车高亮*/}{/* 购物车数量 */}<div className={classNames('icon', carList.length > 0 && 'fill')}>{carList.length > 0 && <div className="cartCornerMark">{carList.length}</div>}</div>{/* 购物车价格 */}<div className="main"><div className="price"><span className="payableAmount"><span className="payableAmountUnit">¥</span>{totalPrice.toFixed(2)}</span></div><span className="text">预估另需配送费 ¥5</span></div>{/* 结算 or 起送 */}{carList.length > 0 ? (<div className="goToPreview">去结算</div>) : (<div className="minFee">1元起送</div>)}</div>{/* 添加visible类名 div会显示出来 */}<div className={classNames('cartPanel')}><div className="header"><span className="text">购物车</span><span className="clearCart">清空购物车</span></div>{/* 购物车列表 */}<div className="scrollArea">{carList.map(item => {return (<div className="cartItem" key={item.id}><img className="shopPic" src={item.picture} alt="" /><div className="main"><div className="skuInfo"><div className="name">{item.name}</div></div><div className="payableAmount"><span className="yuan">¥</span><span className="price">{item.price}</span></div></div><div className="skuBtnWrapper btnGroup">{/* 数量组件 */}<Countcount={item.count}/></div></div>)})}</div></div></div>)
}export default Cart
7.购物车列表功能实现


1.takeaway.js
// 编写storeimport { createSlice } from "@reduxjs/toolkit"
import axios from "axios"const foodsStore = createSlice({name: 'foods',initialState: {// 商品列表foodsList: [],//激活indexactiveIndex:0,//汽车carList:[]},reducers: {// 更改商品列表setFoodsList (state, action) {state.foodsList = action.payload},//更改activeIndexchangeActiveIndex(state,action){state.activeIndex = action.payload},setCarlist(state,action){// 是否添加过?以action.payload.id去cartList中匹配 匹配到了 添加过const item = state.carList.find(item => item.id === action.payload.id)if (item) {item.count++} else {state.carList.push(action.payload)}},increCount(state,action){const item = state.carList.find(item => item.id === action.payload.id)item.count++},decreCount(state,action){const item = state.carList.find(item => item.id === action.payload.id)if(item.count===0){return}item.count--},// 清除购物车clearCart (state) {state.carList = []}}
})// 异步获取部分
const { setFoodsList,changeActiveIndex,setCarlist,increCount,decreCount,clearCart} = foodsStore.actions
const fetchFoodsList = () => {return async (dispatch) => {// 编写异步逻辑const res = await axios.get('http://localhost:3004/takeaway')// 调用dispatch函数提交actiondispatch(setFoodsList(res.data))}
}export { fetchFoodsList ,changeActiveIndex,setCarlist,increCount,decreCount,clearCart}const reducer = foodsStore.reducerexport default reducer
2.cart下index文件
import classNames from 'classnames'
import { useDispatch, useSelector } from 'react-redux'
import Count from '../Count'
import './index.scss'
import {increCount,decreCount,clearCart} from '../../store/modules/takeaway'const Cart = () => {const { carList } = useSelector(state => state.foods)// 计算总价 const totalPrice = carList.reduce((a, c) => a + c.price * c.count, 0)const dispatch = useDispatch()return (<div className="cartContainer"><div className="cart">{/* fill 添加fill类名购物车高亮*/}{/* 购物车数量 */}<div className={classNames('icon', carList.length > 0 && 'fill')}>{carList.length > 0 && <div className="cartCornerMark">{carList.length}</div>}</div>{/* 购物车价格 */}<div className="main"><div className="price"><span className="payableAmount"><span className="payableAmountUnit">¥</span>{totalPrice.toFixed(2)}</span></div><span className="text">预估另需配送费 ¥5</span></div>{/* 结算 or 起送 */}{carList.length > 0 ? (<div className="goToPreview">去结算</div>) : (<div className="minFee">1元起送</div>)}</div>{/* 添加visible类名 div会显示出来 */}<div className={classNames('cartPanel',carList.length>0&&'visible')} ><div className="header"><span className="text">购物车</span><span className="clearCart" onClick={()=>dispatch(clearCart())}>清空购物车</span></div>{/* 购物车列表 */}<div className="scrollArea">{carList.map(item => {return (<div className="cartItem" key={item.id}><img className="shopPic" src={item.picture} alt="" /><div className="main"><div className="skuInfo"><div className="name">{item.name}</div></div><div className="payableAmount"><span className="yuan">¥</span><span className="price">{item.price}</span></div></div><div className="skuBtnWrapper btnGroup">{/* 数量组件 */}<Countcount={item.count}onPlus={()=>dispatch(increCount({id:item.id}))}onMinus={()=>dispatch(decreCount({id:item.id}))}/></div></div>)})}</div></div></div>)
}export default Cart
8.控制购物车显示和隐藏


1.cart文件下index.js文件
import classNames from 'classnames'
import { useDispatch, useSelector} from 'react-redux'
import { useState } from 'react'
import Count from '../Count'
import './index.scss'
import {increCount,decreCount,clearCart} from '../../store/modules/takeaway'const Cart = () => {const { carList } = useSelector(state => state.foods)// 计算总价 const totalPrice = carList.reduce((a, c) => a + c.price * c.count, 0)const [visible,setVisible]= useState(false)const dispatch = useDispatch()const onShow = () => {if (carList.length > 0) {setVisible(true)}}return (<div className="cartContainer">{/* 遮罩层 添加visible类名可以显示出来 */}<divclassName={classNames('cartOverlay', visible && 'visible')}onClick={() => setVisible(false)}/><div className="cart">{/* fill 添加fill类名购物车高亮*/}{/* 购物车数量 */}<div onClick={onShow} className={classNames('icon', carList.length > 0 && 'fill')}>{carList.length > 0 && <div className="cartCornerMark">{carList.length}</div>}</div>{/* 购物车价格 */}<div className="main"><div className="price"><span className="payableAmount"><span className="payableAmountUnit">¥</span>{totalPrice.toFixed(2)}</span></div><span className="text">预估另需配送费 ¥5</span></div>{/* 结算 or 起送 */}{carList.length > 0 ? (<div className="goToPreview">去结算</div>) : (<div className="minFee">1元起送</div>)}</div>{/* 添加visible类名 div会显示出来 */}<div className={classNames('cartPanel',visible &&'visible')} ><div className="header"><span className="text">购物车</span><span className="clearCart" onClick={()=>dispatch(clearCart())}>清空购物车</span></div>{/* 购物车列表 */}<div className="scrollArea">{carList.map(item => {return (<div className="cartItem" key={item.id}><img className="shopPic" src={item.picture} alt="" /><div className="main"><div className="skuInfo"><div className="name">{item.name}</div></div><div className="payableAmount"><span className="yuan">¥</span><span className="price">{item.price}</span></div></div><div className="skuBtnWrapper btnGroup">{/* 数量组件 */}<Countcount={item.count}onPlus={()=>dispatch(increCount({id:item.id}))}onMinus={()=>dispatch(decreCount({id:item.id}))}/></div></div>)})}</div></div></div>)
}export default Cart相关文章:
react + redux 之 美团案例
1.案例展示 2.环境搭建 克隆项目到本地(内置了基础静态组件和模版) git clone http://git.itcast.cn/heimaqianduan/redux-meituan.git 安装所有依赖 npm i 启动mock服务(内置了json-server) npm run serve 启动前端服务 npm…...
【形式语言与自动机/编译原理】CFG-->Greibach-->NPDA(2)
本文将详细讲解《形式语言与自动机》(研究生课程)或《编译原理》(本科生课程)中的上下文无关文法(CFG)转换成Greibach范式,再转成下推自动机(NPDA)识别语言是否可以被接受…...
14.用户管理
目录 1、权限表 1、user表 1.用户列 2.权限列 3.安全列 4.资源控制列 2、db表和host 表 1.用户列 2.权限列 3. tables_priv 表和 columns _priv 表 4.procs_priv 表 2、账户管理 1. 登录和退出MySQL服务器 2、创建普通用户: 1.使用CREATE USER语创建…...
【交叉编译环境】安装arm-linux交叉编译环境到虚拟机教程(简洁版本)
就是看到了好些教程有些繁琐,我就写了一个 我这个解压安装的交叉编译环境是Linaro GCC的一个版本,可以用于在x86_64的主机上编译arm-linux-gnueabihf的目标代码 步骤来了 在你的Ubuntu系统中创建一个目录,例如/usr/local/arm,然后…...
感染了后缀为.[sqlback@memeware.net].2700勒索病毒如何应对?数据能够恢复吗?
导言: 近期,[sqlbackmemeware.net].2700 勒索病毒成为网络安全的一大威胁。该勒索病毒采用高度复杂的加密算法,将用户文件加密并勒索赎金。了解该病毒的特征对于有效恢复被加密数据以及预防进一步感染至关重要。如果受感染的数据确实有恢复的…...
[Linux开发工具]——vim使用
Linux编辑器——vim的使用 一、什么是集成开发环境?二、什么是vim?三、vim的概念四、vim的基本操作五、vim命令模式命令集5.1 移动光标5.2 删除文字5.3 复制粘贴5.4 其他操作 六、vim底行模式命令集6.1 首先在命令模式下shift;进入末行模式。…...
【教学类-43-11】 20231231 3*3宫格数独提取单元格坐标数字的通用模板(做成2*2=4套、3*2=6套)
背景需求: 1、以前做单元格填充,都是制作N个分开的单元格 (表格8) 2、这次做五宫格数独的Word模板,我图方便,就只用了一个大表格,第六行第六列隐藏框线,看上去就是分开的ÿ…...
Spring Boot日志:从Logger到@Slf4j的探秘
写在前面 Hello大家好,今日是2024年的第一天,祝大家元旦快乐🎉 2024第一篇文章从SpringBoot日志开始 文章目录 一、前言二、日志有什么用?三、日志怎么用?四、自定义日志打印💬 常见日志框架说明4.1 在程序…...
英飞凌TC3xx之一起认识GTM系列(六)如何实现GTM与VADC关联的配置
英飞凌TC3xx之一起认识GTM系列(六)如何实现GTM与VADC关联的配置 1 GTM与ADC的接口2 GTM与VADC的连接2.1 VADC 到 GTM 的连接2.1.1 简要介绍2.1.2 应用举例2.2 EVADC到 GTM的连接2.2.1 应用举例3 总结本文介绍实现GTM与VADC的连接性的相关寄存器配置。 1 GTM与ADC的接口 由英…...
【基础】【Python网络爬虫】【6.数据持久化】Excel、Json、Csv 数据保存(附大量案例代码)(建议收藏)
Python网络爬虫基础 数据持久化(数据保存)1. Excel创建数据表批量数据写入读取表格数据案例 - 豆瓣保存 Excel案例 - 网易新闻Excel保存 2. Json数据序列化和反序列化中文指定案例 - 豆瓣保存Json案例 - Json保存 3. Csv写入csv列表数据案例 - 豆瓣列表保…...
王道考研计算机网络——应用层
如何为用户提供服务? CS/P2P 提高域名解析的速度:local name server高速缓存:直接地址映射/低级的域名服务器的地址 本机也有告诉缓存:本机开机的时候从本地域名服务器当中下载域名和地址的对应数据库,放到本地的高…...
Android MVVM 写法
前言 Model:负责数据逻辑 View:负责视图逻辑 ViewModel:负责业务逻辑 持有关系: 1、ViewModel 持有 View 2、ViewModel 持有 Model 3、Model 持有 ViewModel 辅助工具:DataBinding 执行流程:View &g…...
LeetCode 热题 100——283. 移动零
283. 移动零 提示 简单 2.3K 相关企业 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,…...
neovim调试xv6-riscv过程中索引不到对应头文件问题
大家好,我叫徐锦桐,个人博客地址为www.xujintong.com,github地址为https://github.com/jintongxu。平时记录一下学习计算机过程中获取的知识,还有日常折腾的经验,欢迎大家访问。 和这篇文章neovim调试linux内核过程中索…...
轻量应用服务器与云服务器CVM对比——腾讯云
腾讯云轻量服务器和云服务器CVM该怎么选?不差钱选云服务器CVM,追求性价比选择轻量应用服务器,轻量真优惠呀,活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年,540元三…...
骑砍战团MOD开发(31)-游戏AI控制
一.骑砍单机模式下AI控制 骑砍战团中野外战斗,训练场中小兵和地方小兵的行为统称为场景AI. 骑砍大地图中敌军追踪和遭遇追击统称为大地图AI. 二.骑砍场景AI 骑砍引擎通过header_mission_templates,py定制AI常量控制小兵位置,动作和朝向.可实现自定义阵型和攻击动作。 # Agen…...
flutter学习-day21-使用permission_handler进行系统权限的申请和操作
文章目录 1. 介绍2. 环境准备2-1. Android2-2. iOS 3. 使用 1. 介绍 在大多数操作系统上,权限不是在安装时才授予应用程序的。相反,开发人员必须在应用程序运行时请求用户的许可。在 flutter 开发中,则需要一个跨平台(iOS, Android)的 API 来…...
虹科方案丨L2进阶L3,数据采集如何助力自动驾驶
来源:康谋自动驾驶 虹科方案丨L2进阶L3,数据采集如何助力自动驾驶 原文链接:https://mp.weixin.qq.com/s/qhWy11x_-b5VmBt86r4OdQ 欢迎关注虹科,为您提供最新资讯! 12月14日,宝马集团宣布,搭载…...
Kubernetes 学习总结(42)—— Kubernetes 之 pod 健康检查详解
Kubernetes 入门 回想 2017 年刚开始接触 Kubernetes 时,碰到 Pod一直起不来的情况,就开始抓瞎。后来渐渐地掌握了一些排查方法之后,这种情况才得以缓解。随着时间推移,又碰到了问题。有一天在部署某个 springboot 微服务时&…...
【后端】Docker学习笔记
文章目录 Docker一、Docker安装(Linux)二、Docker概念三、Docker常用命令四、数据卷五、自定义镜像六、网络七、DockerCompose Docker Docker是一个开源平台,主要基于Go语言构建,它使开发者能够将应用程序及其依赖项打包到一个轻…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
