javascript?Redux的狀態(tài)管理詳解
所謂的狀態(tài)管理,就是對(duì)應(yīng)用程序中的數(shù)據(jù)進(jìn)行管理。
理念:凡是數(shù)據(jù)流管理混亂的項(xiàng)目,幾乎都上不了線。好的項(xiàng)目,必須有非常良好的數(shù)據(jù)流管理。
如何使用Redux?記住“3個(gè)3”。
第1個(gè)三:3個(gè)api,createStore、combineReducers、applyMiddleware
第2個(gè)三:3個(gè)特點(diǎn),store單一數(shù)據(jù)源、store只讀的、只能通過reducer純函數(shù)來修改store。
第3個(gè)三:3個(gè)概念,store、action、reducer。
基本概念:
- state 包含所有數(shù)據(jù),用來給store提供數(shù)據(jù)
- store 就是狀態(tài)管理數(shù)據(jù),可以被React共享的數(shù)據(jù),數(shù)據(jù)容器,保存數(shù)據(jù)的地方
- action 是一種信號(hào),可以用來修改state的信號(hào),固定格式:{type,payload},可以這樣理解,type是郵件標(biāo)題,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是一種信號(hào),可以用來修改state的信號(hào)
// 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ù)的
問題:在這個(gè)函數(shù)式組件中,如何與redux關(guān)聯(lián)
答案:
1.connect高階組件,它是把redux相關(guān)的數(shù)據(jù)和方法,放到props上。
2.hooks,它是直接訪問,與props無關(guān)
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才會(huì)接收到
return {
count: state.count,
msg: state.msg
}
}
function mapDispatchToProps(dispatch) {
// dispatch用于派發(fā)一個(gè)信號(hào)(action),信號(hào)可以修改store
console.log('dispatch', dispatch);
return {
// 需求:添加方法使count自增或自減
add: function () {
// 在這里通過 dispatch 向store派發(fā)一個(gè)'自增'的信號(hào)
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會(huì)接收到信號(hào),改造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是一種信號(hào),可以用來修改state的信號(hào)
// action的格式是固定的{type,payload}
function reducer(state = initState, action) {
console.log('信號(hào)', action);
// 由于store是只讀的,直接修改state是不會(huì)更新視圖的
// 所以對(duì)store進(jìn)行深復(fù)制
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最終效果:

當(dāng)然,代碼中還有很多可以改進(jìn)的地方,例如,通常我們不使用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來實(shí)現(xiàn)深復(fù)制: produce:第一個(gè)參數(shù)就是傳入舊的state,經(jīng)過內(nèi)部深復(fù)制,在第二個(gè)函數(shù)中可以拿到深復(fù)制的結(jié)果;在回調(diào)函數(shù)中對(duì)深復(fù)制的結(jié)果進(jìn)行修改(加工),最終修改的結(jié)果就是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深復(fù)制
// produce:第一個(gè)參數(shù)就是傳入舊的state,經(jīng)過內(nèi)部深復(fù)制,在第二個(gè)函數(shù)中可以拿到深復(fù)制的結(jié)果;在回調(diào)函數(shù)中對(duì)深復(fù)制的結(jié)果進(jìn)行修改(加工),最終修改的結(jié)果就是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工作原理示意圖

總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
第二次聊一聊JS require.js模塊化工具的基礎(chǔ)知識(shí)
第二次聊一聊JS require.js模塊化工具的基礎(chǔ)知識(shí),本文為大家JS require.js模塊化工具的最基本知識(shí)點(diǎn),感興趣的小伙伴們可以參考一下2016-04-04
JS實(shí)現(xiàn)簡單網(wǎng)頁倒計(jì)時(shí)器
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)簡單網(wǎng)頁倒計(jì)時(shí)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
JavaScript+HTML5實(shí)現(xiàn)的日期比較功能示例
這篇文章主要介紹了JavaScript+HTML5實(shí)現(xiàn)的日期比較功能,涉及javascript結(jié)合HTML5針對(duì)日期的轉(zhuǎn)換與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-07-07
js使用navigator.userAgent判斷當(dāng)前瀏覽器所處的環(huán)境
本文主要介紹了js使用navigator.userAgent判斷當(dāng)前瀏覽器所處的環(huán)境,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
原生 JS Ajax,GET和POST 請(qǐng)求實(shí)例代碼
這篇文章主要介紹了原生 JS Ajax,GET和POST 請(qǐng)求實(shí)例代碼的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
javascript設(shè)計(jì)模式 – 代理模式原理與用法實(shí)例分析
這篇文章主要介紹了javascript設(shè)計(jì)模式 – 代理模式,結(jié)合實(shí)例形式分析了javascript代理模式相關(guān)概念、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04
JS實(shí)現(xiàn)將二維數(shù)組轉(zhuǎn)為json格式字符串操作示例
這篇文章主要介紹了JS實(shí)現(xiàn)將二維數(shù)組轉(zhuǎn)為json格式字符串操作,涉及javascript數(shù)組遍歷、拼接、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下2018-07-07

