react + redux 之 美团案例

1.案例展示

![](https://img-blog.csdnimg.cn/direct/b7a9604e5d274504ad630427a996aa8b.png
在这里插入图片描述

2.环境搭建

  1. 克隆项目到本地(内置了基础静态组件和模版)
git clone http://git.itcast.cn/heimaqianduan/redux-meituan.git 
  1. 安装所有依赖
npm i 
  1. 启动mock服务(内置了json-server)
npm run serve 
  1. 启动前端服务
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

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

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

相关文章

ES6之Proxy详解

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

六、Redis 分布式系统 —— 超详细操作演示!

六、Redis 分布式系统 —— 超详细操作演示&#xff01; 六、Redis 分布式系统6.1 数据分区算法6.1.1 顺序分区6.1.2 哈希分区 6.2 系统搭建与运行6.2.1 系统搭建6.2.2 系统启动与关闭 6.3 集群操作6.3.1 连接集群6.3.2 写入数据6.3.3 集群查询6.3.4 故障转移6.3.5 集群扩容6.3…

BGP路由知识点

目录 1.BGP的工作原理&#xff1a; 2.BGP路由的一般格式&#xff1a; 3.三种不同的自治系统AS 4.BGP的路由选择 5.BGP的四种报文 BGP&#xff08;Border Gateway Protocol&#xff09;是一种用于自治系统&#xff08;AS&#xff09;之间的路由选择协议。它是互联网中最常用…

Spark SQL中的聚合与窗口函数

Spark SQL是Apache Spark的一个模块&#xff0c;用于处理结构化数据。在数据分析和处理中&#xff0c;聚合和窗口函数是非常重要的工具&#xff0c;它们可以对数据进行各种汇总、计算和分析。本文将深入探讨Spark SQL中的聚合与窗口函数&#xff0c;包括聚合函数、分组操作、窗…

算法训练营Day34(贪心算法)

1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 秒了 class Solution {public int largestSumAfterKNegations(int[] nums, int k) {Arrays.sort(nums);// -4 -3 -2 -1 5//-2 -2 0 2 5int last -1;for(int i 0;i<…

【JavaFX】基于JavaFX11 构建可编辑、对象存储、修改立即保存、支持条件过滤的TableView

文章目录 效果设计思路二、使用步骤前提:自定义TableView的失去焦点事件1. 创建实体类2.读取本地文件数据3. 定义表格TableView总结效果 如图所示,这是一个存储application.properties内容的表格。这里的文件application.properties是从Linux服务器上获取来的。 当点击检索按…

【算法】使用位运算解算法题(C++)

文章目录 0. 位运算 基本介绍1. 位运算基本使用 连带题目191.位1的个数338.比特位计数461.汉明距离136.只出现一次的数字260.只出现一次的数字III 2. 使用位运算解决算法题面试题01.01.判定字符是否唯一371.两整数之和137.只出现一次的数字II面试题17.04.消失的数字面试题17.1…

SDG大数据平台简介

联合国可持续发展目标&#xff08;Sustainable Development Goals&#xff09;缩写SDGs&#xff0c;是联合国制定的17个全球发展目标&#xff0c;在2000-2015年千年发展目标&#xff08;MDGs&#xff09;到期之后继续指导2015-2030年的全球发展工作。&#xff08;摘自百度&…

React学习计划-React16--React基础(八)react-redux使用与优化,纯函数介绍

笔记gitee地址 学习了 redux,为什么还要讲react-redux呢&#xff1f; redux不是专门为react所创建的,只不过在某一刻&#xff0c;react和redux看对眼了&#xff0c;所以俩人走到了一起&#xff0c;所以为了更好的支持redux,react官方出了react-redux来更好的支持redux 1. react…

Couchdb 垂直权限绕过漏洞(CVE-2017-12635)

一、漏洞描述 Apache CouchDB是一个开源数据库&#xff0c;专注于易用性和成为”完全拥抱web的数据库”。它是一个使用JSON作为存储格式&#xff0c;JavaScript作为查询语言&#xff0c;MapReduce和HTTP作为API的NoSQL数据库。应用广泛&#xff0c;如BBC用在其动态内容展示平台…

【Unity入门】UGUI之Slider(滑动条)

目录 一、什么是Slider&#xff1f;二、Slider属性与功能 一、什么是Slider&#xff1f; Slider控件允许用户可以通过鼠标来在预先确定的范围调节数值 我们可以在Hierarchy视图右键 -> UI ->Slider来创建滑动条 通过上图可以发现Unity内置的Slider主要有3部分&#x…

JAVA:面向对象1

类和对象 public String sayHello(){ //修饰符/ /返回值类型/ /方法名/ /方法的参数/ return "hello,world!"; return 返回值&#xff1b; } /* void 可以不写返回值&#xff0c;return一个空就行 &#xff1a; return; return 结束方法&#xff…

一些想法:关于行人检测与重识别

本文主要是介绍我们录用于 ECCV18 的一个工作&#xff1a;Person Search via A Mask-guided Two-stream CNN Model. 这篇文章着眼于 Person Search 这个任务&#xff0c;即同时考虑行人检测&#xff08;Pedestrian Detection&#xff09;与行人重识别&#xff08;Person Re-ide…

Vue:使用IDEA开发Vue的相关配置

一、IDEA无法识别.vue文件 1、IDEA 添加Vue插件 2、添加Vue配置 File | Settings | Editor | File Types 找到 HTML 文件 在下面点号 输入*.vue 二、IDEA无法创建.vue文件 1、问题 在开发过程中&#xff0c;发现创建文件的界面&#xff0c;没有vue模板 2、相关配置 Fi…

2024年01月IDE流行度最新排名

点击查看最新IDE流行度最新排名&#xff08;每月更新&#xff09; 2024年01月IDE流行度最新排名 顶级IDE排名是通过分析在谷歌上搜索IDE下载页面的频率而创建的 一个IDE被搜索的次数越多&#xff0c;这个IDE就被认为越受欢迎。原始数据来自谷歌Trends 如果您相信集体智慧&am…

基于JAVA的学校热点新闻推送系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 新闻类型模块2.2 新闻档案模块2.3 新闻留言模块2.4 新闻评论模块2.5 新闻收藏模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 新闻类型表3.2.2 新闻表3.2.3 新闻留言表3.2.4 新闻评论表3.2.5 新闻收藏表 四、系统展…

Mysql基础总结

一、MySql基础 MySQL常见面试题 一、索引相关 &#xff08;1&#xff09;什么是索引? 索引是一种数据结构&#xff0c;可以帮助我们快速的进行数据的查找。 &#xff08;2&#xff09;索引是个什么样的数据结构呢? 索引的数据结构和具体存储引擎的实现有关&#xff0c;…

vue中$nextTick作用和实例

为什么要使用nextTick&#xff1f; vue中DOM更新是异步执行&#xff0c;相当于我们在修改数据的时候&#xff0c;视图是不会立即更新的&#xff0c;会先把新的数据攒一赞&#xff0c;例如假如v-for更新这三个数据item1和item2和item3&#xff0c;按照vue的特性dom更新的特性会…

FPGA项目(13)——基于FPGA的电梯控制系统

1.摘要 随着科技的发展&#xff0c;电梯早在上个世纪就已进入人们的生活。对于电梯的控制&#xff0c;传统的方法是使用继电器——接触器控制系统进行控制。随着EDA技术的发展&#xff0c;FPGA已广泛应用于各项电子设计中&#xff0c;本设计即利用FPGA来实现对电梯控制系统的设…

助力打造智慧数字课堂,基于YOLOv7【tiny/l/x】开发构建教学课堂场景下学生课堂行为检测识别分析系统

近年来&#xff0c;随着行为检测技术的发展&#xff0c;分析学生在课堂视频中的行为&#xff0c;以获取他们的课堂状态和学习表现信息已经成为可能。这项技术对学校的教师、管理人员、学生和家长都非常重要。使用深度学习方法自动检测学生的课堂行为是分析学生课堂表现和提高教…