0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

6-React Redux

Posted at

一:Redux快速上手

image.png
image.png
image.png
image.png

// 1.state:管理的数据初始状态    action:对象type 标记当前想要做什么样的修改
function reducer (state = {count:0},action){
  // 数据不可变:基于原始状态生成一个新的状态
  if(action.type==="INCREMENT"){
     return{count:state.count + 1}
  }
    if(action.type==="DECREMENT"){
   return{count:state.count - 1}
  }
  return state
}

// 2.
const store = Redux.createStore(reducer)
// 3.回调函数可以在每次State发生变化的时候自动执行
store.subscribe(()=>{
 console.log("state变化了",store.getState())
 document.getElementById("count").innerText = store.getState().count
})
// 4.
const inBtn = document.getElementById("increment")
inBtn.addEventListener("click",()=>{
// 增
store.dispatch({
type:"INCREMENT"
})
})

const dBtn = document.getElementById("decrement")
dBtn.addEventListener("click",()=>{
// 减
store.dispatch({
type:"DECREMENT"
})
})
// 5.

二:Redux与React-环境准备

image.png
image.png
image.png

三:Redux与React-实现counter

image.png
image.png
在counterStore.js中

import {createSlice} from "@reduxjs/toolkit"

const counterStore = createSlice({
 name:"counter",
 // 初始化state
 initialState{
  count:0
 },
 // 修改状态的方法,同步方法 支持直接修改
 reducers:{
   inscrement(state){
     state.count++
   },
   decrement(state){
   state.count--
   }
 }
})

// 解构出来actionCreater函数
const {inscrement,decrement } = counterStore.actions
// 获取reducer
const reducer = counterStore.reducer
// 以按需导出的方式导出actionCreater
export {inscrement,decrement}
// 以默认导出的方式导出reducer
export default reducer

index.js

import {configureStore} from "@reduxjs/toolkit"
//导入子模块reducer
import counterReducer from "./modules/counterStore"

const store = configureStore({
 reducer:{
    counter:counterReducer
 }
})
export default store

image.png
index.js
image.png
image.png
App.js

import {useDispatch,useSelector} from "react-redux"
// 导入actionCreater
import {inscrement,decrement } from "./store/modules/counterStore"
function App(){
 const {count} = useSelector(state => state.counter)
 const dispatch = useDispatch()
  return(
   <div className="App">
   <button onClick={() => dispatch(decrement())}>-</button>
   {count}
   <button onClick={() => dispatch(inscrement())}>+</button>
   </div>
  )
}

image.png
image.png

四:Redux与React-提交action传参

image.png
image.png
image.png

五:Redux与React-异步状态操作

image.png
image.png
channelStore.js

import {createSlice} from "@reduxjs/toolkit"
import axios from "axios"

const channelStore = createSlice({
  name:"channel",
  initialState:{
   channelList:[]
  },
  reducers:{
    setChannels(state,action){
    state.channelList = action.payload
    }
  }
})

// 异步请求部分
const {setChannels} = channelStore.actions

const fetchChannlList = () =>{
  return async (dispatch)=>{
   const res = await axios.get("url")
   dispatch(setChannels(res.data.data.channels))
  }
}

export {fetchChannlList}

const reducer = channelStore.reducer

export default reducer

index.js

import {configureStore} from "@reduxjs/toolkit"

//导入子模块reducer
import counterReducer from "./modules/counterStore"
import channelReducer from "./modules/channelStore"
const store = configureStore({
 reducer:{
    counter:counterReducer
    channel:channelReducer
 }
})
export default store

App.js
image.png

六:Redux调试-devtools

七:美团案例

1.案例演示和环境准备

image.png
image.png
image.png

2.分类和商品列表渲染

image.png
image.png
package.json

npm run serve
run start

store-modules-takeaway.js

// 编写store
import {createSlice} from "@reduxjs/toolkit"

const foodsStore = createSlice({
   name:"foods",
   initialState:{
    // 商品列表
    foodList:[]
   },
   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}
export default reducer

index.js

import foodsReducer from "./modules/takeaway"
import {configureStore} from "@reduxjs/toolkit"

const store = configureStore({
 reducer:{
  foods:foodsReducer
 }
})
export default store

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>
)

App.js

import {useDispatch, useSelector} from "react-redux"
import {fetchFoodsList} from "./store/modules/takeaway"
// 触发action执行
// 1.useDispatch -> dispatch  2.actionCreater导入进来
// 3.useEffect

const dispatch = useDispatch()
useEffect (() => {
  dispatch(fetchFoodsList())
},[dispatch])

// 获取foodsList渲染数据列表
// 1.useSelector
const {foodsList} = useSelector(state =>state.foods)

3.点击分类激活交互实现

image.png
image.png
index.js

// 菜单激活下标值
activeIndex:0
// 更改activeIndex
changeActiveIndex(state,action){
  state.activeIndex = action.payload
}

const {setFoodsList, changeActiveIndex} = foodsStore.actions
export {changeActiveIndex}

index.js

import {changeActiveIndex} from "../../store/modules/takeaway"
const dispatch = useDispatch()
onClick={() => dispatch(changeActiveIndex(index))}

const {foodsList,activeIndex} = useSelector(state => state.foods)
activeIndex === index && "active"

4.商品列表切换显示

image.png
App.js

activeIndex === index && <FoodsCategory
  key={item.tag}
   // 列表标题
  name={item.name}
   // 列表商品
  foods={item.foods}
  />

5.添加购物车实现

image.png
image.png
takeaway.js

// 购物车列表
cartList:[]

// 添加购物车
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}

index.js

import {addCart} fron "../../../store/modules/takeaway"
const dispatch = useDispatch()
<span className="plus" onClick={()=>dispatch(addCart({
  id,
  picture,
  name,
  unit,
  description,
  food_tag_list,
  month_saled,
  like_ratio_desc,
  price,
  tag,
  count
}))}></span>

6.添加区域功能实现

image.png
image.png
index.js

const {cartList} = useSelector(state=>state.foods)
// 计算总价
const totalPrice = cartList.reduce((a,c) => a+c.price*c.count,0)
{totalPrice.toFixed(2)}

<div className={classNames("icon",cartList.length > 0 && "fill")}>
  {cartList.length > 0 && <div className="cartCornerMark">{cartList.length}</div>}
</div>


{cartList.length > 0 && <div className = "cartCornerMark">{cartList.length}</div>}

// 结算起送
{cartList.length > 0 ?(
 <div className = "goToPreview">去结算</div>
 ) : (
 <div className="minFee">1元起送</div>
)}

7.购物车列表功能实现

image.png
image.png
image.png
index.js

<div className={classNames("cartPanel","visible")}>
</div>

takeaway.js

// count增
increCount(state,action){
  // 关键点:找到当前要修改谁的count id
const item =   state.cartList.find(item=>item.id===action.payload.id)
item.count++
},
// count减
decreCount(state,action){
  // 关键点:找到当前要修改谁的count id
const item =   state.cartList.find(item=>item.id===action.payload.id)
item.count--
},
const {increCount,decreCount} = foodsStore.action
export{increCount,decreCount}

index.js

import {increCount,decreCount} from "../../store/modules/takeaway"

const dispatch = useDispatch()

// 数量组件
<Count
  count={item.count}
  onPlus={()=> dispatch(increCount({id:item.id}))}
  onMinus={()=> dispatch(decreCount({id:item.id}))}
/>

takeaway.js

// count增
increCount(state,action){
  // 关键点:找到当前要修改谁的count id
const item =   state.cartList.find(item=>item.id===action.payload.id)
item.count++
},
// count减
decreCount(state,action){
  // 关键点:找到当前要修改谁的count id
const item =   state.cartList.find(item=>item.id===action.payload.id)
if(item.count === 0){
 return
}
item.count--
},
// 清除购物车
clearCart(state){
  state.cartList = []
}
const {increCount,decreCount,clearCart} = foodsStore.action
export{increCount,decreCount,clearCart}

index.js

import {clearCart} from "../../store/modules/takeaway"
<span className = "clearCart" onClick={() => dispatch(clearCart)} >
清空购物车
</span>

8.控制购物车显示和隐藏

image.png
uploading...0
index.js

// 控制购物车打开关闭的状态
const [visible, setVisible] = useState(false)

<div 
 className={classNames("cartOverlay",visible && "visible")}
 onClick ={()=>setVisible(false)}
/>

<div onClick ={onShow} className={classNames("icon",cartList.length > 0 && "fill")}>
  {cartList.length > 0 && <div className="cartCornerMark">{cartList.length}</div>}
</div>

const onShow=()=>{
 if(cartList.length > 0){
   setVisible(true)
 }
}

<div 
 className={classNames("cartPanel",visible && "visible")}>
</div>

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?