網站首頁 編程語言 正文
1. 簡介
Redux 是 JavaScript 應用的狀態容器(對象),提供可預測的狀態管理。可以讓你開發出行為穩定可預測的應用,運行于不同的環境(客戶端、服務器、原生應用),并且易于測試。Redux 除了和 React 一起用外,還支持其它界面庫。
解決的問題:多層級組件間通信問題。
2. 核心概念
單一數據源
整個redux中的數據都是集中管理,存儲于同一個數據源中,數據源中的數據為單向數據流,不可直接修改。
純函數 (reducer) 統一對 state 數據修改
redux 定義了一個 reducer 函數來完成 state 數據的修改,reducer 會接收先前的 state 和 action,并返回新的 state。
- 函數執行結果是可預期的(多次調用結果相同)
- 函數執行不會觸發副作用
- 函數中的變量,沒有使用外部的
3. redux工作流
①、store通過 reducer 創建了初始狀態
②、component 通過 store.getState() 獲取到了 store 中保存的 state 掛載在了自己的狀態上
③、用戶產生了操作,調用了 actions 的方法
④、actions 的方法被調用,創建了帶有標示性信息的 action(描述對象)
⑤、actions 將 action 通過調用 store.dispatch 方法發送到了 reducer 中
⑥、reducer 接收到 action 并根據標識信息判斷之后返回了新的 state
⑦、store 的 state 被 reducer 更改為新 state 的時候,store.subscribe 方法里的回調函數會執行,此時就可以通知 component 去重新獲取 state
4. 模擬redux工作流程
redux.js:
// 自定義的redux狀態管理 // 用 createStore 方法接收 reducer 純函數 export const createStore = reducer => { // 接收新的帶有單一數據源的對象 let state = undefined // 訂閱隊列 let tasks = [] // 3.store.dispatch({type,payload}) const dispath = action => { // 將 action 交給 reducer ,返回一個新的數據源 state = reducer(state, action) // 數據源發生變化時,讓訂閱隊列中的每一個回調函數執行 tasks.forEach(cb => cb()) } const subscribe = cb => { // 把回調函數放入訂閱隊列中 tasks.push(cb) // 取消訂閱時,刪除訂閱隊列中的回調函數 return () => tasks.splice(tasks.indexOf(cb), 1) } // 返回數據源 const getState = () => state // 2.初始化,防止組件第一次調用 getState 得到的是 undefined dispath({ type: '@@init@@' }) // 返回 redux 工作流中需要的三個函數 return { dispath, subscribe, getState } }
index.js:
// 導入倉庫 import { createStore } from './redux' // 5.設置一個初始值 const initState = { num: 100 } // 4.創建 reducer 純函數 const reducer = (state = initState, action) => { // 完成組件中加的操作 if (action.type === 'add') return { ...state, num: state.num + action.payload } return state; } const store = createStore(reducer) export default store
App.jsx:
import React, { Component } from 'react' // 組件中導入倉庫 import store from './store' class App extends Component { componentDidMount() { // 訂閱 redux 的頻道,只要頻道發生更改,就會觸發視圖更新 // 并且讓 unsubscribe 接收到 redux 中取消訂閱的函數 this.unsubscribe = store.subscribe(() => this.forceUpdate()) } componentWillUnmount() { // 取消訂閱,組件卸載時執行 this.unsubscribe() } render() { return ( <div> {/* 1.組件通過 getState 得到數據 */} <h3>{store.getState().num}</h3> <hr /> <button onClick={() => { // 動作:添加;數據:每次加2 store.dispath({ type: 'add', payload: 2 }) }} > ++++ </button> </div> ) } } export default App
5. 使用redux
安裝 redux:
redux 沒有內嵌在 react 框架中,使用時需要手動去安裝:yarn add redux
安裝 redux-devtools:
安裝第3方模塊,讓調試工具顯示 state:
# yarn add -D @redux-devtools/extension import { composeWithDevTools } from '@redux-devtools/extension' const store = createStore( reducer, composeWithDevTools() );
把上述案例,用真實的 redux 實現一下:
index.js:
// 1.導入redux中的createStore創建倉庫數據的方法 import { createStore } from 'redux' // 配合瀏覽器安裝的插件來進行redux調試所用 // 開發時有用,生產要關閉 import { composeWithDevTools } from '@redux-devtools/extension' // 2.初始state數據 const initState = { num: 100 } // 3.定義一個純函數reducer,專門用來操作state中的數據,要返回一個新的state const reducer = (state = initState, action) => { if (action.type === 'add') return { ...state, num: state.num + action.payload } return state; } // 得到數據對象 let store // 開發與生產環境的判斷,提高安全性 process.env.NODE_ENV === 'development' ? store = createStore( reducer, composeWithDevTools() ) : store = createStore( reducer ) // 導出 export default store
6. react-redux
概述:
React-Redux 是 Redux 的官方針對 React 開發的擴展庫,默認沒有在 React 項目中安裝,需要手動來安裝。react-redux 是依賴于 redux,所以你必須安裝 redux。
你可以理解為 react-redux 就是 redux 給我們提供一些高階組件,能解決的問題是:使用它以后我們不需要在每個組件中再去手動訂閱數據的更新了,方便了 react 組件中調用 redux 中的數據。
安裝:
yarn add react-redux
使用步驟:
在程序主文件 index.js 文件中,定義 Provider。此處類似于之前跨組件通信處的 Provider 一樣,旨在讓全局的組件共享 store 中的數據。
import React from 'react' import ReactDOM from 'react-dom' import App from './App' // 導入Provider生產數據者組件 import { Provider } from 'react-redux' // 導入數據源 import store from './store' ReactDOM.render( // 包裹所有的路由 <Provider store={store}> <App /> </Provider>, document.getElementById('root') )
在組件中使用 react-redux
import React, { Component } from 'react' // 提供一個高階組件 connect 用來把 redux 中的 state 和 action 映射到當前組件的 props 中 import { connect } from 'react-redux' // 此函數必須要返回一個json對象 // 函數的 state 參數就是 redux 中的 state 數據 const mapStateToProps = state => { return { num: state.num } } // mapStateToProps 函數的兩種簡寫寫法 // const mapStateToProps = state => state // @connect(state => state, mapDispatchToProps) // 此函數必須要返回一個json對象 // dispatch 就是之前通過 store.dispatch 的方法 const mapDispatchToProps = dispatch => { return { add(n = 1) { // 動作:增加,數據:n dispatch({ type: 'add', payload: n }) } } } // 函數的方式可以同步也可以異步,dispatch 是你手動在需要的地方來調用 // const mapDispatchToProps = dispatch => { // return { // add(n = 1) { // setTimeout(() => { // dispatch({ type: 'add', payload: n }) // }, 1000) // } // } // } // 該函數的對象寫法: // 如果為對象方式則只能使用同步,不能用異步,因為在 connect 實現時如果是對象,則它會主動調用 dispatch // 調用了 dispatch 它就立刻執行。而如果是一個異步,則就會不符合 dispatch 要求,則報錯 // const mapDispatchToProps = { // add: (n = 1) => ({ type: 'add', payload: n }) // } // 參數1:函數,把 redux 中的 state 數據映射到當前的 props 屬性中 // 參數2:函數|對象,把你操作的 dispatch 方法映射到當前的 props 屬性中 @connect(mapStateToProps, mapDispatchToProps) class App extends Component { render() { console.log('props', this.props) return ( <div> <h3>{this.props.num}</h3> <hr /> <button onClick={() => this.props.add()}>++++</button> </div> ) } } export default App
上面是使用裝飾器的寫法,還有不使用裝飾器的寫法:
我們需要將裝飾器一行注釋,并且修改導出方式。
原文鏈接:https://blog.csdn.net/weixin_45605541/article/details/127061122
相關推薦
- 2022-10-02 Blender?Python編程創建發光材質示例詳解_python
- 2022-05-25 spring的構造函數注入屬性@ConstructorBinding
- 2023-07-26 TypeScript中的泛型(泛型函數、接口、類、泛型約束)
- 2022-11-24 redis使用skiplist跳表的原因解析_Redis
- 2023-05-21 Pycharm如何對python文件進行打包_python
- 2022-08-10 淺談pandas關于查看庫或依賴庫版本的API原理_python
- 2022-10-24 C#?Winform實現自定義漂亮的通知效果_C#教程
- 2022-06-30 Python利用shutil模塊實現文件夾的復制刪除與裁剪_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支