react 之 美团案例
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 之 美团案例
1.案例展示 2.环境搭建 克隆项目到本地(内置了基础静态组件和模版) git clone http://git.itcast.cn/heimaqianduan/redux-meituan.git 安装所有依赖 npm i 启动mock服务(内置了json-server) npm run serve 启动前端服务 npm…...
C基础使用
return 0; 语句用于表示退出程序。 一个程序有且只能有一个main函数的存在 安装编译环境: 安装vim: ubuntu里vim编辑器使用方法_ubuntu vim-CSDN博客 编译与运行: gcc hello.c //编译源文件 ./a.out //运行…...
Linux网络编程——Socket编程步骤及常用API
Sockt服务器和客户端的开发步骤 TCP connect()最好建立在listen()后,一旦监听到就建立连接。 UDP 常用API 包含头文件 #include<sys/types.h> #include<sys/socket.h>创建套接字(连接协议) 作用 用于根据指定的地址族、数据…...
数据挖掘 K-Means聚类
未格式化之前的代码: import pandas as pd#数据处理 from matplotlib import pyplot as plt#绘图 from sklearn.preprocessing import MinMaxScaler#归一化 from sklearn.cluster import KMeans#聚类 import os#处理文件os.environ["OMP_NUM_THREADS"] …...
医疗卫生行业网络安全需求发展
文章目录 一、行业安全建设需求分析1、等级保护2.0合规建设云计算技术大数据技术物联网技术移动互联网技术2、加强医疗数据安全保护加密存储与传输数据加强数据备份与恢复注重数据脱敏与分级保护3、强化网络安全制度管理完善应急预案与响应机制加强网络安全人员管理二、行业新技…...
【Unity热更新】学会AssetsBundle打包、加载、卸载
本教程详细讲解什么是AssetBundle压缩包机制!然后构建 AssetBundle、加载 AssetBundle 以及卸载 AssetBundle 的简要教程。这一个流程就是热更新! AssetBundles 简介 1.什么是AssetBundles? AssetBundles是Unity中一种用于打包和存储资源(如模型、纹理、声音等)的文件格…...
智能优化算法应用:基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.指数分布算法4.实验参数设定5.算法结果6.…...
vue 监听浏览器关闭或刷新事件
vue 监听浏览器关闭或刷新事件 需求 web项目中使用socket时,涉及到关闭刷新浏览器多次连接问题,其中一个解决方法是在关闭或刷新浏览器时,将连接断开。 代码 <script> export default {// 可以在created、beforeMount或mounted生命…...
VuePress-theme-hope 搭建个人博客 2【快速上手】 —— 安装、部署 防止踩坑篇
续👆VuePress、VuePress-theme-hope 搭建个人博客 1【快速上手】 项目常用命令 vuepress dev [dir] 会启动一个开发服务器,以便让你在本地开发你的 VuePress 站点。vuepress build [dir] 会将你的 VuePress 站点构建成静态文件,以便你进行后…...
ClickHouse基础知识(四):ClickHouse 引擎详解
1. 表引擎的使用 表引擎是 ClickHouse 的一大特色。可以说, 表引擎决定了如何存储表的数据。包括: ➢ 数据的存储方式和位置,写到哪里以及从哪里读取数据。 默认存放在/var/lib/clickhouse/data ➢ 支持哪些查询以及如何支持。 ➢ 并发数…...
关于设计模式、Java基础面试题
前言 之前为了准备面试,收集整理了一些面试题。 本篇文章更新时间2023年12月27日。 最新的内容可以看我的原文:https://www.yuque.com/wfzx/ninzck/cbf0cxkrr6s1kniv 设计模式 单例共有几种写法? 细分起来就有9种:懒汉&#x…...
Python爱心光波完整代码
文章目录 环境需求完整代码详细分析环境需求 python3.11.4PyCharm Community Edition 2023.2.5pyinstaller6.2.0(可选,这个库用于打包,使程序没有python环境也可以运行,如果想发给好朋友的话需要这个库哦~)【注】 python环境搭建请见:https://want595.blog.csdn.net/arti…...
PowerShell Instal 一键部署gitea
gitea 前言 Gitea 是一个轻量级的 DevOps 平台软件。从开发计划到产品成型的整个软件生命周期,他都能够高效而轻松的帮助团队和开发者。包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD。它与 GitHub、Bitbucket 和 GitLab 等比较类似。 Gitea 最初是从 Gogs 分支而来…...
C语言——指针题目“指针探测器“
如果你觉得你指针学的自我感觉良好,甚至已经到达了炉火纯青的地步,不妨来试试这道题目? #include<stdio.h> int main() {char* c[] { "ENTER","NEW","POINT","FIRST" };char** cp[] { c 3…...
Hive讲课笔记:内部表与外部表
文章目录 一、导言二、内部表1.1 什么是内部表1.1.1 内部表的定义1.1.2 内部表的关键特性 1.2 创建与操作内部表1.2.1 创建并查看数据库1.2.2 在park数据库里创建student表1.2.3 在student表插入一条记录1.2.4 通过HDFS WebUI查看数据库与表 三、外部表2.1 什么是外部表2.2 创建…...
Docker本地部署开源浏览器Firefox并远程访问进行测试
文章目录 1. 部署Firefox2. 本地访问Firefox3. Linux安装Cpolar4. 配置Firefox公网地址5. 远程访问Firefox6. 固定Firefox公网地址7. 固定地址访问Firefox Firefox是一款免费开源的网页浏览器,由Mozilla基金会开发和维护。它是第一个成功挑战微软Internet Explorer浏…...
PHP:服务器端脚本语言的瑰宝
PHP(Hypertext Preprocessor)是一种广泛应用于服务器端编程的开源脚本语言,它以其简单易学、灵活性和强大的功能而成为Web开发的瑰宝。本文将深入介绍PHP的历史、特性、用途以及与生态系统的关系,为读者提供对这门语言全面的了解。…...
【MySQL】数据库并发控制:悲观锁与乐观锁的深入解析
🍎个人博客:个人主页 🏆个人专栏: 数 据 库 ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 悲观锁(Pessimistic Locking): 乐观锁(Optimistic Locking): 总结&#x…...
作业--day38
1.定义一个Person类,包含私有成员,int *age,string &name,一个Stu类,包含私有成员double *score,Person p1,写出Person类和Stu类的特殊成员函数,并写一个Stu的show函数ÿ…...
pytest 的 fixture 固件机制
一、前置说明 固件(fixture)是一些函数,pytest 会在执行测试函数之前(或之后)加载运行它们。pytest 使用 fixture 固件机制来实现测试的前置和后置操作,可以方便地设置和共享测试环境。 二、操作步骤 1. 编写测试代码 atme/demos/demo_pytest_tutorials/test_pytest_…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...
