javascript?Redux的狀態(tài)管理詳解
所謂的狀態(tài)管理,就是對應用程序中的數(shù)據(jù)進行管理。
理念:凡是數(shù)據(jù)流管理混亂的項目,幾乎都上不了線。好的項目,必須有非常良好的數(shù)據(jù)流管理。
如何使用Redux?記住“3個3”。
第1個三:3個api,createStore、combineReducers、applyMiddleware
第2個三:3個特點,store單一數(shù)據(jù)源、store只讀的、只能通過reducer純函數(shù)來修改store。
第3個三:3個概念,store、action、reducer。
基本概念:
- state 包含所有數(shù)據(jù),用來給store提供數(shù)據(jù)
- store 就是狀態(tài)管理數(shù)據(jù),可以被React共享的數(shù)據(jù),數(shù)據(jù)容器,保存數(shù)據(jù)的地方
- action 是一種信號,可以用來修改state的信號,固定格式:{type,payload},可以這樣理解,type是郵件標題,payload是郵件內(nèi)容
示例:在src目錄下新建store文件夾,新建index.js
// store/index.js import { createStore } from 'redux' // 定義在redux中的數(shù)據(jù),可被Reac組件共享 const initState = { count: 1, msg: 'hello world' } // state參數(shù),就是狀態(tài)管理數(shù)據(jù),可以被React共享的數(shù)據(jù) // action是一種信號,可以用來修改state的信號 // action的格式是固定的{type,payload} function reducer(state = initState, action) { return state } const store = createStore(reducer) export default store
在src下新建目錄views,good,GoodList.js
// views/good/GoodList.js export default props => { console.log('GoodList props', props); return ( <div> <h1>商品列表頁</h1> </div> ) }
App.js
// 引入Provider來提供數(shù)據(jù) import { Provider } from 'react-redux' import store from '@/store'; import GoodList from '@/views/good/GoodList'; // store就是state function App() { return ( <Provider store={store}> <GoodList /> </Provider> ); } export default App;
打印GoodList props為空,直接使用props是拿不到數(shù)據(jù)的
問題:在這個函數(shù)式組件中,如何與redux關聯(lián)
答案:
1.connect高階組件,它是把redux相關的數(shù)據(jù)和方法,放到props上。
2.hooks,它是直接訪問,與props無關
connect 語法:connect(mapStateToProps,mapDispatchToProps)
理解:mapStateToProps用于把store數(shù)據(jù)放在props上,mapDispatchToProps用于把修改store的方法放到props上
改造views/good/GoodList.js:
import { connect } from 'react-redux' // 語法:connect(mapStateToProps,mapDispatchToProps)(UI組件) // 理解:mapStateToProps用于把store數(shù)據(jù)放在props上,mapDispatchToProps用于把修改store的方法放到props上 function mapStateToProps(state) { console.log('上下文中的store', state); // 把獲得的數(shù)據(jù)return出去,props才會接收到 return { count: state.count, msg: state.msg } } function mapDispatchToProps(dispatch) { // dispatch用于派發(fā)一個信號(action),信號可以修改store console.log('dispatch', dispatch); return { // 需求:添加方法使count自增或自減 add: function () { // 在這里通過 dispatch 向store派發(fā)一個'自增'的信號 const action = { type: 'add', payload: 1 } dispatch(action) }, sub: function () { const action = { type: 'sub', payload: 1 } dispatch(action) } } } export default connect(mapStateToProps, mapDispatchToProps)( props => { console.log('GoodList props', props); return ( <div> <h1>商品列表頁</h1> <h1>{props.count}</h1> <button onClick={props.add}>自增</button> <button onClick={props.sub}>自減</button> </div> ) } )
store會接收到信號,改造store/index.js:
// store/index.js import { createStore } from 'redux' // 定義在redux中的數(shù)據(jù),可被Reac組件共享 const initState = { count: 1, msg: 'hello world' } // state參數(shù),就是狀態(tài)管理數(shù)據(jù),可以被React共享的數(shù)據(jù) // action是一種信號,可以用來修改state的信號 // action的格式是固定的{type,payload} function reducer(state = initState, action) { console.log('信號', action); // 由于store是只讀的,直接修改state是不會更新視圖的 // 所以對store進行深復制 let newState = JSON.parse(JSON.stringify(state)) if (action.type === 'add') { newState.count += action.payload } if (action.type === 'sub') { newState.count -= action.payload } // console.log('newState',newState) return newState } const store = createStore(reducer) export default store
最終效果:
當然,代碼中還有很多可以改進的地方,例如,通常我們不使用connect,而是使用Hooks函數(shù)來直接訪問store里面數(shù)據(jù),而無需通過props
- useSelector() 用于訪問上下文中的redux數(shù)據(jù)
- useDispatch() 得到dispatch方法,可以向redux派送
將views/good/GoodList.js改造成hooks函數(shù)寫法,極大減少代碼量
import { useSelector, useDispatch } from "react-redux"; // 注意:Hooks只能在函數(shù)式組件中使用 // - useSelector() 用于訪問上下文中的redux數(shù)據(jù) // - useDispatch() 得到dispatch方法,可以向redux派送action export default () => { // 訪問根state中study子模塊中的count const count = useSelector(state => state.count) const dispatch = useDispatch() const add = (payload) => dispatch({ type: 'add', payload }) const sub = (payload) => dispatch({ type: 'sub', payload }) return ( <div> <h1>商品列表頁</h1> <h1>{count}</h1> <button onClick={() => add(1)}>自增</button> <button onClick={() => sub(1)}>自減</button> </div> ) }
以及我們還可以通過produce來實現(xiàn)深復制: produce:第一個參數(shù)就是傳入舊的state,經(jīng)過內(nèi)部深復制,在第二個函數(shù)中可以拿到深復制的結果;在回調(diào)函數(shù)中對深復制的結果進行修改(加工),最終修改的結果就是produce的返回值,
將store/index.js改造如下:
import { produce } from 'immer' // 定義在redux中的數(shù)據(jù),可被Reac組件共享 const initState = { count: 1, msg: 'hello world' } function reducer(state = initState, action) { // immer深復制 // produce:第一個參數(shù)就是傳入舊的state,經(jīng)過內(nèi)部深復制,在第二個函數(shù)中可以拿到深復制的結果;在回調(diào)函數(shù)中對深復制的結果進行修改(加工),最終修改的結果就是produce的返回值 return produce(state, (newState) => { switch (action.type) { case 'add': newState.count += action.payload break case 'sub': newState.count -= action.payload break default: } }) } export default reducer
還可以使用 logger 中間件更加直觀的查看數(shù)據(jù)流
import { createStore, combineReducers, applyMiddleware } from 'redux'
import logger from 'redux-logger'
const store = createStore(reducer, applyMiddleware(logger))
export default store
使用效果如圖:
redux工作原理示意圖
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內(nèi)容!
相關文章
JavaScript+HTML5實現(xiàn)的日期比較功能示例
這篇文章主要介紹了JavaScript+HTML5實現(xiàn)的日期比較功能,涉及javascript結合HTML5針對日期的轉換與運算相關操作技巧,需要的朋友可以參考下2017-07-07js使用navigator.userAgent判斷當前瀏覽器所處的環(huán)境
本文主要介紹了js使用navigator.userAgent判斷當前瀏覽器所處的環(huán)境,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-04-04javascript設計模式 – 代理模式原理與用法實例分析
這篇文章主要介紹了javascript設計模式 – 代理模式,結合實例形式分析了javascript代理模式相關概念、原理、用法及操作注意事項,需要的朋友可以參考下2020-04-04JS實現(xiàn)將二維數(shù)組轉為json格式字符串操作示例
這篇文章主要介紹了JS實現(xiàn)將二維數(shù)組轉為json格式字符串操作,涉及javascript數(shù)組遍歷、拼接、轉換等相關操作技巧,需要的朋友可以參考下2018-07-07