react 之 美团案例

发布时间:2023年12月28日

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函数提交action
    dispatch(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.useEffect
  const dispatch = useDispatch()
  useEffect(() => {
    dispatch(fetchFoodsList())
  }, [dispatch])
  // 获取foodsList渲染数据列表
  // 1. useSelector
  const { foodsList } = useSelector(state => state.foods)
   {/* 外卖商品列表 */}
              {foodsList.map((item, index) => {
                return (
                 <FoodsCategory
                    key={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: [],
    //激活index
    activeIndex:0,
  },
  reducers: {
    // 更改商品列表
    setFoodsList (state, action) {
      state.foodsList = action.payload
    },
    //更改activeIndex
    changeActiveIndex(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 (
          <div
          onClick={() => 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 && <FoodsCategory
                    key={item.tag}
                    // 列表标题
                    name={item.name}
                    // 列表商品
                    foods={item.foods}
                  />
                )
              })}
            </div>

5.添加购物车

在这里插入图片描述
1.takeaway.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
    },
    // 更改activeIndex
    changeActiveIndex (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">
                  {/* 数量组件 */}
                  <Count
                    count={item.count}
                 
                  />
                </div>
              </div>
            )
          })}
        </div>
      </div>
    </div>
  )
}

export default Cart


7.购物车列表功能实现

在这里插入图片描述
在这里插入图片描述

文章来源:https://blog.csdn.net/weixin_42268006/article/details/135269686
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。