程序员书籍笔记 程序员书籍笔记
  • HTML
  • CSS
  • JavaScript
  • 前端知识
  • Vue
  • MarkDown
  • git
  • Node.js
  • Linux
  • 51单片机
  • 四级
  • 第一学期课程
  • 操作系统
  • 计算机网络
  • 数据结构
  • 计算机组成原理
  • HTML5
  • Electron
  • 日记便签
  • 前端导航
GitHub (opens new window)
  • HTML
  • CSS
  • JavaScript
  • 前端知识
  • Vue
  • MarkDown
  • git
  • Node.js
  • Linux
  • 51单片机
  • 四级
  • 第一学期课程
  • 操作系统
  • 计算机网络
  • 数据结构
  • 计算机组成原理
  • HTML5
  • Electron
  • 日记便签
  • 前端导航
GitHub (opens new window)
  • HTML

  • CSS

  • JavaScript

  • GO

  • 正则表达式

  • java

  • TypeScript

  • react

    • 组件
    • this指向
    • 受控组件
    • 组件通信
    • 案例及同级组件通信
    • Props和插槽
    • 生命周期
    • 路由
    • 极客PC项目
    • 组件复用
    • hooks
    • hooks更多用法
    • Reudx
      • Redux
      • redux基本概念
        • action
        • action-creator
        • reducer
        • store
      • react-redux
        • 不使用react-redux的使用
        • 使用 react-redux 包
      • redux处理异步
      • 分离变量名
      • 多个reducer合并
      • redux开发工具
    • todo案例
    • react函数组件
    • 基本使用
  • 前端知识

  • jQuery

  • Python

  • C和C++

  • 前端和后端
  • react
yuadh
2022-08-02
目录

Reudx

# Redux

状态管理工具

React 全家桶

  • react 核心 - react hooks
  • react-router (react-router-dom)
  • 状态管理 - mobx(简单)/ redux(复杂)
  • 中间件:redux-thunk 、 redux-saga

# redux基本概念

核心概念 :store 、action 、reducer

  • store :仓库(存储数据), 管理 action 和 reducer
  • action :表示一个动作或者行为的抽象
  • reducer :根据 action 来对数据加工返回新数据

# action

actions 是任务的抽象,试图中的每个用户交互都是一个 action ,比如:添加任务、删除任务、登录、加入购物车灯

  • 本质上是一个 js 普通对象
  • action 内必须使用一个字符串类型 type 的唯一标识
  • action 如果数量过多,需要采用模块化的方式管理
1. action是一个js对象
2. action必须提供type属性,表示动作的类型
3. type属性的值是一个字符串,采用全大写字母表示,多个单词使用_连接
{
	type: "INCREMENT"
}
4. action中除了type,还可以指定动作需要的其他数据
{
	type: "ADD_TODO",
	todoName: '学习redux'
}
5. 将来要完成的所有功能,都抽象成了一个个的动作
1
2
3
4
5
6
7
8
9
10
11
12

# action-creator

用来创建 action 的函数,直接使用对象来创建 action 不灵活,参数写死. 一般使用函数来创建 action ,一般把创建 action 的函数叫做 actionCreator

  • action creator创建函数只是简单的返回一个 action
  • action creator创建函数的好处是更容易被移植和测试
 const delTodo = (id) => ({ type: 'DEL_TODO', id })
 console.log(delTodo(5))
1
2

# reducer

reducer 是一个 纯函数 ,接收旧的 state 和 action ,返回新的 state

  • reducer的state需要有一个默认值,这个默认值就是redux的初始值

  • reducer内部需要判断action的type,根据type进行处理,处理的时候不能修改原来的数据

  • educer如果遇到不认识的type,一定要返回原来的state(重要)

示例

function reducer(state = 0, action) {
  switch (action.type) {
    case 'ADD':
      return state + 1
    case 'MINUS':
      return state - 1
    default:
      return state
  }
}
1
2
3
4
5
6
7
8
9
10

纯函数

特点:只要是固定的输入,必定是固定的输出

原则:

  • 不能改写参数

  • 不能调用 Date.now() 等函数

  • 不能使用全局变量

  • 没有副作用

# store

  • getState
  • dispatch
  • subscribe 订阅

store 是把 action 、reducer 联系到一起的对象

// store
 const { createStore } = window.Redux
// 参数1: reducer
 const store = createStore(reducer)
1
2
3
4
  • 通过 getState() 方法可以获取到 state 数据

     document.querySelector('span').innerHTML = store.getState()
    
    1
  • 通过 dispatch(action) 方法可以派遣任务更新 state 数据

    document.querySelector('.add').onclick = function () {
    	store.dispatch(add())
    }
    
    1
    2
    3
  • 通过 subscribe(listener) 方法可以订阅数据的更新

    // 订阅:只要state发生了变化,这个订阅的回调函数就会执行。
    // 返回值:调用了就会取消订阅
    const unsubscribe = store.subscribe(() => {
      console.log(store.getState())
      document.querySelector('span').innerHTML =store.getState()
    })
    unsubscribe()//停止监听
    
    1
    2
    3
    4
    5
    6
    7

# react-redux

以上 redux 的使用和 react 是相互独立的 ,要配合 react 的使用需要使用到 react-redux 包

  • react-redux

  • redux-devtools-extension

  • redux-thunk

# 不使用react-redux的使用

action.js

export const add = (count) => {
  return {
    type: 'ADD',
    count,
  }
}
1
2
3
4
5
6

reducers.js

export const addReducer = (
  state = {
    count: 1,
  },
  action
) => {
  switch (action.type) {
    case 'ADD':
      return Object.assign({}, state, { count: action.count })
    default:
      return state
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

store\index.js

import ReactDOM from 'react-dom'
import App from './App.js'
import { createStore } from 'redux'
import { addReducer } from "./store/reducers"
let store = createStore(addReducer)
ReactDOM.render(<App store={store}></App>, document.querySelector('#root'))
store.subscribe(() => {
  ReactDOM.render(<App store={store}></App>, document.querySelector('#root'))
})
1
2
3
4
5
6
7
8
9

App.js

import { add } from './store/actions'
const App = (props) => {
  const {
    store: { getState, dispatch },
  } = props
  const { count } = getState()
  return (
    <div>
      <h3>App</h3>
      <p>{count}</p>
      <button
        onClick={() => {
          dispatch(add(2))
        }}
      >
        点我+2
      </button>
    </div>
  )
}

export default App
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 使用 react-redux 包

store.js

// 创建store
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store

1
2
3
4
5
6

reducers.js

function reducer(state = 100, action) {
  console.log(action)
  if (action.type === 'ADD') return state + 1
  if (action.type === 'MINUS') return state - 1
  return state
}

export default reducer

1
2
3
4
5
6
7
8
9

App.js

// react和redux没有关系
import Child from './Child'
export default function App() {
  return (
    <div>
      <h1>根组件</h1>
      <div>我被点击了0次</div>

      <hr />
      <Child></Child>
    </div>
  )
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

src\index.js

import React from 'react'
import ReactDom from 'react-dom'
import App from './App'
import { Provider } from 'react-redux'
import store from './store'
/* 
  react-redux的使用步骤
    1. 安装 yarn add react-redux
    2. 导入Provider组件 并且使用Provider组件包裹App组件
    3. 在任意的子组件中都可以获取到store
*/

ReactDom.render(
  <Provider store={store}>
    <App></App>
  </Provider>,
  document.getElementById('root')
)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Child.js

import { useSelector, useDispatch } from 'react-redux'
import { add } from './store/action'
export default function Child() {
  // 调用useStore就可以得到store对象
  // 调用useSelector 得到 store中数据
  // const store = useStore()
  const count = useSelector((state) => state)
  const dispatch = useDispatch()
  return (
    <div>
      <h3>我是子组件---点击了{count}次</h3>
      <button onClick={() => dispatch(add())}>修改</button>
    </div>
  )
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

重点步骤

  • 使用 <Provider></Provider> 包裹 <App> 根组件为所有子组件提供 store
  • useStore 获取 store 对象
  • useSelector 获取 state 数据
  • useDispatch 获取派遣任务的函数

# redux处理异步

redux-thunk

import {createStore,applyMiddleware} from 'redux'
import reducer from './reducer'
import thunk from 'redux-thunk'
const store = createStore(reducer,applyMiddleware(thunk))
export default store
1
2
3
4
5

配置

//如果是同步的 action , 直接返回一个 action 对象
//如果是异步的 aciton , 需要返回一个异步的函数 , 在异步函数中,处理完之后 , 需要在异步函数中 dispatch
export const buy = (money) =>{
  return {
    type:'BUY',
    money,
  }
}
export const buyAsync = (money) =>{
  return (dispatch)=>{
    setTimeout(()=>{dispatch(buy(money))},3000)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

使用

<button onClick={()=>dispatch(buyAsync(300))}></button>

# 分离变量名

  • 新建 action_type.js 文件
  • 在文件中 const ADD_MONEY = 'ADD_MONEY' 声明变量
  • export 导出 import {} 导入
  • 使用更加方便管理

# 多个reducer合并

combineReducers(reducers)

在 reducers 文件下有多个 reducer 需要导入给 store 使用 ,需要使用到这个合并的 API .

a

function user(state = {name:'y',age:20},action){
  	return state
}
1
2
3

b

function money(state = 100,action){
  	return state
}
1
2
3

合并

const rootReducer = combineReducers({
  a:user,
  b:money
})
export default rootReducer
1
2
3
4
5

使用

const money = useSelector((state)=>state.money)

const user= useSelector((state)=>state.user)

# redux开发工具

  • 浏览器安装 react-redux 开发工具
  • 安装和导入 redux-devtools-extension 包

使用

import {composeWithDevTools} from 'redux-devtools-extension'

const store = createStore(reducer,composeWithDevTools(applyMiddleware(thunk)))
1
2
3

配置好后可以在浏览器中打开

编辑 (opens new window)
上次更新: 2023/02/07, 14:51:48
hooks更多用法
todo案例

← hooks更多用法 todo案例→

Theme by Vdoing | Copyright © 2021-2023 yuadh
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×