react购物车Redux

devtools/2025/1/16 5:57:33/

入口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.ppmy.cn/devtools/107628.html

相关文章

mac电脑里面的 磁盘分区,容器,宗卷,宗卷组的理解和使用

在mac电脑里面我们一般都是使用宗卷&#xff0c;他和我们常见的pc机器硬盘的分区是有区别的。 对于物理硬盘来说 不管是分区还是宗卷&#xff0c;他们都是逻辑上面的概念。 分区 mac电脑里面的分区 和 pc电脑中的分区差不多&#xff0c; 他们都是针对的物理硬盘&#xff0c;…

3、无重复字符的最长子串

题目 链接&#xff1a;leetcode链接 思路分析&#xff08;滑动窗口&#xff09; 子串是连续的&#xff0c;很容易联想到滑动窗口&#xff0c;处理连续子串问题很方便。 先设置left和right两个指针&#xff0c;从0位置开始移动。 为了去判断窗口里面有没有出现重复的子串&a…

Android系统去掉WIFI模块

先说应用场景&#xff0c;有些特定设备&#xff0c;不能连接wifi。需要隐藏的模块&#xff0c;QS面板模块的wifi,还有设置里面的wifi.由于QS属于SystemUI&#xff0c;熟悉SystemUI之后&#xff0c;就可以直接去SystemUi那里找&#xff0c;找到QSTitle 默认配置的地方。 一、…

傅里叶变换家族

禹晶、肖创柏、廖庆敏《数字图像处理&#xff08;面向新工科的电工电子信息基础课程系列教材&#xff09;》 禹晶、肖创柏、廖庆敏《数字图像处理》资源二维码

Sqlite3数据库的学习

数据存储方式 1、内存存数据:当程序运行结束&#xff0c;掉电&#xff0c;数据丢失。(数组、链表、变量等) 2、硬盘存数据:程序运行结束&#xff0c;掉电&#xff0c;数据不丢失 (1)文件:对数据管理(增删改查)效率低. (2)数据库:专业存储数据&#xff0c;可存大量数据。对数…

请解释一下 Java 中的多线程。如何创建一个新的线程?如何保证线程安全?

Java 中的多线程是指在一个程序中同时执行多个任务的能力。这可以显著提高应用程序的性能&#xff0c;尤其是在多核处理器上。多线程编程涉及到创建和管理线程&#xff0c;以及确保线程之间的数据共享和同步。 如何创建一个新的线程&#xff1f; 在 Java 中&#xff0c;创建一…

docker实战扩展三(dockerfile中run的详细用法)

RUN 是 Dockerfile 中的一个重要指令,用于在镜像构建过程中执行命令。它将在镜像构建过程中创建一个新的临时容器,执行指定的命令,并将执行结果提交到镜像层。每一个 RUN 指令都会创建一个新的镜像层。 RUN 指令的基本用法 Shell 形式 最常见的形式是 shell 形式,这种形…

元宇宙先驱,城市区块链

blockcity 务实元宇宙的先行者,去中心化自治组织开放平台,轻松加入或创建你的DAO组织创新采用Web3和区块链思维,blockcity 真正人人可用,无需下载安装