入口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