react购物车Redux

入口index.js

import React from 'react'
import {createRoot} from 'react-dom/client'import App from './App'
//注入store
import {Provider} from "react-redux";
import store from "./store";const root = createRoot(document.getElementById('root'))
root.render(<Provider store={store}><App/></Provider>
)

srotre/modules/takeway.js

//编写store
import {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},// 更改activeIndexchangActiveIndex(state, action) {state.activeIndex = action.payload},//添加购物车addCart(state, action) {//是否添加过  如果添加只更新count 没有添加过 直接push进去const data = JSON.parse(JSON.stringify(state.cartList))const item = data.find(item => item.id === action.payload.id)const index = data.findIndex(item => item.id === action.payload.id)console.log(item)if (item) {state.cartList[index].count++} else {state.cartList.push(action.payload)}},//count增加addCount(state, action) {const data = JSON.parse(JSON.stringify(state.cartList))const item = data.find(item => item.id === action.payload.id)const index = data.findIndex(item => item.id === action.payload.id)state.cartList[index].count++},//count--decreCount(state, action) {const data = JSON.parse(JSON.stringify(state.cartList))const item = data.find(item => item.id === action.payload.id)const index = data.findIndex(item => item.id === action.payload.id)if (state.cartList[index].count === 0) {return}state.cartList[index].count--},// 清除购物车clearCart (state) {state.cartList = []}}
})
//异步获取部分 结构出创建action对象
const { setFoodsList, changActiveIndex, addCart, addCount, decreCount, clearCart } = foodsStore.actions
console.log(foodsStore.actions, 11111111111)
const fetchChannelList = () => {console.log('123')return async (dispatch) => {console.log('编写异步逻辑')// 编写异步逻辑const res = await axios.get('http://localhost:3004/takeaway')// 调用dispatch函数提交actiondispatch(setFoodsList(res.data))}
}
export { fetchChannelList, changActiveIndex, addCart, addCount, decreCount, clearCart }
//获取reducer函数
const reducer = foodsStore.reducerexport default reducer

srotre/modules/index.js

import foodsReducer from './modules/takeaway'
import { configureStore } from '@reduxjs/toolkit'const store = configureStore({reducer: {foods: foodsReducer}
})export default store

Menus/index.js

import classNames from 'classnames'
import './index.scss'
import {useDispatch, useSelector} from "react-redux";
import {changActiveIndex} from "../../store/modules/takeaway";const Menu = () => {// const foodsList = [//   {//     "tag": "318569657",//     "name": "一人套餐",//     "foods": [//       {//         "id": 8078956697,//         "name": "烤羊肉串(10串)",//         "like_ratio_desc": "好评度100%",//         "month_saled": 40,//         "unit": "10串",//         "food_tag_list": ["点评网友推荐"],//         "price": 90,//         "picture": "https://zqran.gitee.io/images/waimai/8078956697.jpg",//         "description": "",//         "tag": "318569657"//       },//       {//         "id": 7384994864,//         "name": "腊味煲仔饭",//         "like_ratio_desc": "好评度81%",//         "month_saled": 100,//         "unit": "1人份",//         "food_tag_list": [],//         "price": 39,//         "picture": "https://zqran.gitee.io/images/waimai/7384994864.jpg",//         "description": "",//         "tag": "318569657"//       },//       {//         "id": 2305772036,//         "name": "鸡腿胡萝卜焖饭",//         "like_ratio_desc": "好评度91%",//         "month_saled": 300,//         "unit": "1人份",//         "food_tag_list": [],//         "price": 34.32,//         "picture": "https://zqran.gitee.io/images/waimai/2305772036.jpg",//         "description": "主料:大米、鸡腿、菜心、胡萝卜",//         "tag": "318569657"//       },//       {//         "id": 2233861812,//         "name": "小份酸汤莜面鱼鱼+肉夹馍套餐",//         "like_ratio_desc": "好评度73%",//         "month_saled": 600,//         "unit": "1人份",//         "food_tag_list": ["“口味好,包装很好~点赞”"],//         "price": 34.32,//         "picture": "https://zqran.gitee.io/images/waimai/2233861812.jpg",//         "description": "酸汤莜面鱼鱼,主料:酸汤、莜面 肉夹馍,主料:白皮饼、猪肉",//         "tag": "318569657"//       }//     ]//   }// ]const {foodsList, activeIndex} = useSelector(state => state.foods)const menus = foodsList.map(item => ({tag: item.tag, name: item.name}))const dispath = useDispatch()return (<nav className="list-menu">{/* 添加active类名会变成激活状态 */}{menus.map((item, index) => {return (<divonClick={() => dispath(changActiveIndex(index))}key={item.tag}className={classNames('list-menu-item',activeIndex === index && 'active')}>{item.name}</div>)})}</nav>)
}export default Menu

FoodsItem.js

import './index.scss'
import { useDispatch } from 'react-redux'
import {addCart} from "../../../store/modules/takeaway";
const Foods = ({id,picture,name,unit,description,food_tag_list,month_saled,like_ratio_desc,price,tag,count
}) => {const dispatch = useDispatch()return (<dd className="cate-goods"><div className="goods-img-wrap"><img src={picture} alt="" className="goods-img" /></div><div className="goods-info"><div className="goods-desc"><div className="goods-title">{name}</div><div className="goods-detail"><div className="goods-unit">{unit}</div><div className="goods-detail-text">{description}</div></div><div className="goods-tag">{food_tag_list.join(' ')}</div><div className="goods-sales-volume"><span className="goods-num">月售{month_saled}</span><span className="goods-num">{like_ratio_desc}</span></div></div><div className="goods-price-count"><div className="goods-price"><span className="goods-price-unit">¥</span>{price}</div><div className="goods-count"><span className="plus" onClick={() => dispatch(addCart({id,picture,name,unit,description,food_tag_list,month_saled,like_ratio_desc,price,tag,count}))}>+</span></div></div></div></dd>)
}export default Foods

Cart.js

import classNames from 'classnames'
import Count from '../Count'
import './index.scss'
import {useDispatch, useSelector} from "react-redux";
import {addCount, clearCart, decreCount} from "../../store/modules/takeaway";
import {useState} from "react";const Cart = () => {const {cartList} = useSelector(state => state.foods)const totalPrice = cartList.reduce((a, c) => a + c.price * c.count, 0)const totalCount = cartList.reduce((a, c) => a + c.count, 0)const dispatch = useDispatch()//控制购物车打开关闭的状态const [visible, setVisible] = useState(false)const onshow = () => {if (cartList.length > 0) {setVisible(true)}}// const cart = []return (<div className="cartContainer">{/* 遮罩层 添加visible类名可以显示出来 */}<div onClick={() => setVisible(false)}className={classNames('cartOverlay', visible && 'visible')}/><div className="cart">{/* fill 添加fill类名可以切换购物车状态*/}{/* 购物车数量 */}<div onClick={onshow} className={classNames('icon')}>{cartList.length && <div className="cartCornerMark">{totalCount}</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 起送 */}{/* 结算 or 起送 */}{cartList.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">{cartList.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(addCount({id: item.id}))}onMinus={() => dispatch(decreCount({id: item.id}))}/></div></div>)})}</div></div></div>)
}export default Cart

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

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

相关文章

9/3作业

一、继承&#xff08;inhert&#xff09; 面向对象三大特征&#xff1a;封装、继承、多态 继承&#xff1a;所谓继承&#xff0c;是类与类之间的关系。就是基于一个已有的类&#xff0c;来创建出一个新类的过程叫做继承。主要提高代码的复用性。 1.1 继承的作用 1> 实现…

基于mediamtx+ffmpeg实现视频推流,基于python-deffcode实现视频拉流

软件依赖&#xff1a;mediamtx、ffmpeg python包依赖&#xff1a;deffcode mediamtx下载地址&#xff1a;https://github.com/bluenviron/mediamtx/releases ffmeg下载地址&#xff1a;https://ffmpeg.org/download.html deffcode安装命令&#xff1a;pip install deffcode 1、…

爬虫练习(猫眼电影解密)

问题 随便拿一篇电影做样例。我们发现猫眼的页面数据在预览窗口中全是小方框。在当我们拿到源码以后&#xff0c;数据全是加密后的。所以我们需要想办法破解加密&#xff0c;拿到数据。 破解过程 1.源码获取问题与破解 分析 在我们刚刚请求url的时候是可以得到数据的&#xff…

Shadow Dom 是什么

概念 官方&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_shadow_DOM 核心&#xff1a;影子 DOM&#xff08;Shadow DOM&#xff09;允许你将一个 DOM 树附加到一个元素上&#xff0c;并且使该树的内部对于在页面中运行的 JavaScript 和…

Proxyless的多活流量和微服务治理

1. 引言 1.1 项目的背景及意义 在当今的微服务架构中&#xff0c;应用程序通常被拆分成多个独立的服务&#xff0c;这些服务通过网络进行通信。这种架构的优势在于可以提高系统的可扩展性和灵活性&#xff0c;但也带来了新的挑战&#xff0c;比如&#xff1a; 服务间通信的复…

合碳智能 × Milvus:探索化学合成新境界——逆合成路线设计

合碳智能&#xff08;C12.ai&#xff09;成立于2022年&#xff0c;致力于运用AI和具身智能技术&#xff0c;为药物研发实验室提供新一代智能化解决方案&#xff0c;推动实验室从自动化迈向智能化&#xff0c;突破传统实验模式与人员的依赖&#xff0c;解决效率和成本的瓶颈&…

电脑错误mfc140.dll丢失怎么办?mfc140.dll丢失如何修复?

在使用基于Microsoft Visual Studio 2015开发的应用程序时&#xff0c;可能会遇到个别组件影响整体功能的情况&#xff0c;其中“mfc140.dll丢失”错误就是常见的一个技术障碍。这个DLL文件属于Microsoft Foundation Class (MFC) Library&#xff0c;它对Windows应用程序的运行…

MySQL record

更改密码&#xff1a; alter user rootlocalhost identified with mysql_native_password by ‘123456’; 注意&#xff1a; 在命令行方式下&#xff0c;每条MySQL的命令都是以分号结尾的&#xff0c;如果不加分号&#xff0c;MySQL会继续等待用户输入命令&#xff0c;直到MyS…

【C++】STL—vector的使用

目录 前言vector的常见构造迭代器的使用vector空间增长问题vector的增删查改尾插和尾删findinsert和erase 前言 vector是表示可变大小数组的序列容器。它就像数组一样&#xff0c;采用连续的存储空间来存储元素&#xff0c;且它的大小可以动态改变。并且vector在访问元素时也非…

AI语音机器人:通过 Azure Speech 实现类人类的交互

语音对话的重要性 在竞争日益激烈的客户互动领域&#xff0c;人工智能语音对话正成为重中之重。随着数字参与者的崛起&#xff0c;组织认识到语音机器人的强大力量&#xff0c;它是一种自然而直观的沟通方式&#xff0c;可以提供类似人类的体验&#xff0c;深度吸引用户&#…

jmeter中上传文件接口,当文件名为中文时出现乱码

1、在jmeter5.1.1中配置上传文件接口&#xff0c;当上传的文件为中文名称时&#xff0c;文件名称会显示乱码如图 2、解决方案是需要更换jmeter/lib/ext文件中的ApacheJMeter_http.jar 包 3、更换jar包经过多次实验&#xff0c;发现有的上传文件接口中文名正常&#xff0c;但是有…

负载均衡--资源申请说明(三)

1.负载方式&#xff1a;分为四层负载和七层负载 2.负载协议&#xff1a;四层负载为TCP和UDP&#xff0c;七层负载为HTTP和HTTPS 4.负载端口&#xff1a;填写虚地址的端口&#xff08;一般与后端服务端口保持一致&#xff09; 5.真实服务IP&#xff1a;指被负载的后台真实服务…

从零开始:理解并实践Prompt Flow

在人工智能领域中&#xff0c;代码先行与模型紧密结合的Prompt Flow逐渐成为开发者关注的新焦点。今天&#xff0c;我们将共同探索如何快速启动Prompt Flow项目&#xff0c;深入了解流&#xff08;flow&#xff09;的概念&#xff0c;并学习如何使用VS Code Extension或YAML来编…

基于Python的机器学习系列(26):PyTorch中的梯度计算

在本篇中&#xff0c;我们将探讨PyTorch的autograd功能&#xff0c;它为张量操作提供自动微分。我们将学习如何使用torch.autograd工具计算梯度并进行反向传播。 自动微分&#xff08;Autograd&#xff09; PyTorch的autograd包自动计算张量的梯度。当一个张量的.requires_gra…

C++和Python混合编程——C++调用Python入门

大纲 代码结构初始化 Python 解释器获取 GIL为什么需要 GIL&#xff1f;GIL 的影响 导入 Python 模块并执行代码释放 GIL终止 Python 解释器 完整代码编译执行结果项目地址 在《C和Python混合编程——Python调用C入门》一文中&#xff0c;我们熟悉了Python调用C编译的动态库的方…

集成电路学习:什么是PWM脉冲宽度调制

一、PWM&#xff1a;脉冲宽度调制 PWM&#xff0c;全称为脉冲宽度调制&#xff08;Pulse Width Modulation&#xff09;&#xff0c;是一种通过调整脉冲信号的宽度来控制电路输出的技术。在PWM中&#xff0c;信号的输出由一系列等幅值的脉冲组成&#xff0c;这些脉冲的宽度根据…

上海亚商投顾:深成指、创业板指均涨超1%,华为产业链反复活跃

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 大小指数昨日走势分化&#xff0c;沪指全天震荡调整&#xff0c;2800点失而复得&#xff0c;深成指、创业板指…

golang

一.go执行流程 4&#xff09;go run运行时间明显要比第一种时间长一点 【3】编译后的文件可以替换名称 二.语法注意 1.源文件以“go”为扩展名 2.程序的执行入口是main&#xff08;&#xff09;函数。 3.严格区分大小写 4.方法由一条条语句构成&#xff0c;每个语句后不需…

Docker安全

Docker安全 和本地共享资源&#xff0c;会有安全性问题 1. Cgroups 对资源的上限进行控制 /sys/devices/system1.1 cpu资源限制 # 进行cpu控制&#xff0c;只使用20%的资源 docker run -it --rm --cpu-period 100000 --cpu-quota 20000 ubuntu# 测试cpu使用 dd if/dev/zer…

【题目全解】蓝桥杯24省赛C++中高级组题干题解

本帖只提供六道编程题的解题思路&#xff0c;部分题目并不提供实际的代码&#xff08;因为我赛时忘记把代码截图下来了&#xff09;。 T1 - 看书 题干描述&#xff1a; 一本书共 n n n 页&#xff0c;小明计划第一天看 x x x 页&#xff0c;此后每一天都要比前一天多看 y y…