欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一篇文章介紹redux、react-redux、redux-saga總結(jié)

 更新時間:2019年05月23日 10:52:44   作者:張不慫  
這篇文章主要介紹了一篇文章介紹redux、react-redux、redux-saga總結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

本篇主要將react全家桶的產(chǎn)品非常精煉的提取了核心內(nèi)容,精華程度堪比精油。各位大人,既然來了,客官您坐,來人,給客官看茶~~

redux

前言

首先,本篇文章要求您對js,react等知識有一定的了解,如果不曾了解,建議您先看一下:React精髓!一篇全概括(急速)

React有props和state:

  1. props意味著父級分發(fā)下來的屬性
  2. state意味著組件內(nèi)部可以自行管理的狀態(tài),并且整個React沒有數(shù)據(jù)向上回溯的能力,這就是react的單向數(shù)據(jù)流

這就意味著如果是一個數(shù)據(jù)狀態(tài)非常復(fù)雜的應(yīng)用,更多的時候發(fā)現(xiàn)React根本無法讓兩個組件互相交流,使用對方的數(shù)據(jù),react的通過層級傳遞數(shù)據(jù)的這種方法是非常難受的,這個時候,迫切需要一個機制,把所有的state集中到組件頂部,能夠靈活的將所有state各取所需的分發(fā)給所有的組件,是的,這就是redux

簡介

  1. redux是的誕生是為了給 React 應(yīng)用提供「可預(yù)測化的狀態(tài)管理」機制。
  2. Redux會將整個應(yīng)用狀態(tài)(其實也就是數(shù)據(jù))存儲到到一個地方,稱為store
  3. 這個store里面保存一棵狀態(tài)樹(state tree)
  4. 組件改變state的唯一方法是通過調(diào)用store的dispatch方法,觸發(fā)一個action,這個action被對應(yīng)的reducer處理,于是state完成更新
  5. 組件可以派發(fā)(dispatch)行為(action)給store,而不是直接通知其它組件
  6. 其它組件可以通過訂閱store中的狀態(tài)(state)來刷新自己的視圖

使用步驟

創(chuàng)建reducer

  • 可以使用單獨的一個reducer,也可以將多個reducer合并為一個reducer,即:combineReducers()
  • action發(fā)出命令后將state放入reucer加工函數(shù)中,返回新的state,對state進行加工處理

創(chuàng)建action

  • 用戶是接觸不到state的,只能有view觸發(fā),所以,這個action可以理解為指令,需要發(fā)出多少動作就有多少指令
  • action是一個對象,必須有一個叫type的參數(shù),定義action類型

創(chuàng)建的store,使用createStore方法

  • store 可以理解為有多個加工機器的總工廠
  • 提供subscribe,dispatch,getState這些方法。

按步驟手把手實戰(zhàn)。

上述步驟,對應(yīng)的序號,我會在相關(guān)代碼標(biāo)出

npm install redux -S // 安裝

import { createStore } from 'redux' // 引入

const reducer = (state = {count: 0}, action) => {----------> ⑴
 switch (action.type){
 case 'INCREASE': return {count: state.count + 1};
 case 'DECREASE': return {count: state.count - 1};
 default: return state;
 }
}

const actions = {---------->⑵
 increase: () => ({type: 'INCREASE'}),
 decrease: () => ({type: 'DECREASE'})
}

const store = createStore(reducer);---------->⑶

store.subscribe(() =>
 console.log(store.getState())
);

store.dispatch(actions.increase()) // {count: 1}
store.dispatch(actions.increase()) // {count: 2}
store.dispatch(actions.increase()) // {count: 3}

自己畫了一張非常簡陋的流程圖,方便理解redux的工作流程

react-redux

剛開始就說了,如果把store直接集成到React應(yīng)用的頂層props里面,只要各個子組件能訪問到頂層props就行了,比如這樣:

<頂層組件 store={store}>
 <App />
</頂層組件>

不就ok了嗎?這就是 react-redux。Redux 官方提供的 React 綁定庫。 具有高效且靈活的特性。

React Redux 將組件區(qū)分為 容器組件 和 UI 組件

  1. 前者會處理邏輯
  2. 后者只負(fù)責(zé)顯示和交互,內(nèi)部不處理邏輯,狀態(tài)完全由外部掌控

兩個核心

Provider

看我上邊那個代碼的頂層組件4個字。對,你沒有猜錯。這個頂級組件就是Provider,一般我們都將頂層組件包裹在Provider組件之中,這樣的話,所有組件就都可以在react-redux的控制之下了,但是store必須作為參數(shù)放到Provider組件中去

<Provider store = {store}>
 <App />
<Provider>

這個組件的目的是讓所有組件都能夠訪問到Redux中的數(shù)據(jù)。

connect

這個才是react-redux中比較難的部分,我們詳細(xì)解釋一下

首先,先記住下邊的這行代碼:

connect(mapStateToProps, mapDispatchToProps)(MyComponent)

mapStateToProps

這個單詞翻譯過來就是把state映射到props中去 ,其實也就是把Redux中的數(shù)據(jù)映射到React中的props中去。
舉個栗子:

 const mapStateToProps = (state) => {
  return {
  // prop : state.xxx | 意思是將state中的某個數(shù)據(jù)映射到props中
  foo: state.bar
  }
 }

然后渲染的時候就可以使用this.props.foo

class Foo extends Component {
 constructor(props){
  super(props);
 }
 render(){
  return(
   // 這樣子渲染的其實就是state.bar的數(shù)據(jù)了
   <div>this.props.foo</div>
  )
 }
}
Foo = connect()(Foo);
export default Foo;

然后這樣就可以完成渲染了

mapDispatchToProps

這個單詞翻譯過來就是就是把各種dispatch也變成了props讓你可以直接使用

const mapDispatchToProps = (dispatch) => { // 默認(rèn)傳遞參數(shù)就是dispatch
 return {
 onClick: () => {
  dispatch({
  type: 'increatment'
  });
 }
 };
}
class Foo extends Component {
 constructor(props){
  super(props);
 }
 render(){
  return(
   
    <button onClick = {this.props.onClick}>點擊increase</button>
  )
 }
}
Foo = connect()(Foo);
export default Foo;

組件也就改成了上邊這樣,可以直接通過this.props.onClick,來調(diào)用dispatch,這樣子就不需要在代碼中來進行store.dispatch了

react-redux的基本介紹就到這里了

redux-saga

如果按照原始的redux工作流程,當(dāng)組件中產(chǎn)生一個action后會直接觸發(fā)reducer修改state,reducer又是一個純函數(shù),也就是不能再reducer中進行異步操作;

而往往實際中,組件中發(fā)生的action后,在進入reducer之前需要完成一個異步任務(wù),比如發(fā)送ajax請求后拿到數(shù)據(jù)后,再進入reducer,顯然原生的redux是不支持這種操作的

這個時候急需一個中間件來處理這種業(yè)務(wù)場景,目前最優(yōu)雅的處理方式自然就是redux-saga

核心講解

1、Saga 輔助函數(shù)

redux-saga提供了一些輔助函數(shù),用來在一些特定的action 被發(fā)起到Store時派生任務(wù),下面我先來講解兩個輔助函數(shù):takeEvery 和 takeLatest

takeEvery

takeEvery就像一個流水線的洗碗工,過來一個臟盤子就直接執(zhí)行后面的洗碗函數(shù),一旦你請了這個洗碗工他會一直執(zhí)行這個工作,絕對不會停止接盤子的監(jiān)聽過程和觸發(fā)洗盤子函數(shù)

例如:每次點擊  按鈕去Fetch獲取數(shù)據(jù)時時,我們發(fā)起一個 FETCH_REQUESTED 的 action。 我們想通過啟動一個任務(wù)從服務(wù)器獲取一些數(shù)據(jù),來處理這個action,類似于

window.addEventLister('xxx',fn)

當(dāng)dispatch xxx的時候,就會執(zhí)行fn方法,

首先我們創(chuàng)建一個將執(zhí)行異步 action 的任務(wù)(也就是上邊的fn):

// put:你就認(rèn)為put就等于 dispatch就可以了;

// call:可以理解為實行一個異步函數(shù),是阻塞型的,只有運行完后面的函數(shù),才會繼續(xù)往下;
// 在這里可以片面的理解為async中的await!但寫法直觀多了!
import { call, put } from 'redux-saga/effects'

export function* fetchData(action) {
 try {
  const apiAjax = (params) => fetch(url, params);
  const data = yield call(apiAjax);
  yield put({type: "FETCH_SUCCEEDED", data});
 } catch (error) {
  yield put({type: "FETCH_FAILED", error});
 }
}

然后在每次 FETCH_REQUESTED action 被發(fā)起時啟動上面的任務(wù),也就相當(dāng)于每次觸發(fā)一個名字為 FETCH_REQUESTED 的action就會執(zhí)行上邊的任務(wù),代碼如下

import { takeEvery } from 'redux-saga'

function* watchFetchData() {

 yield* takeEvery("FETCH_REQUESTED", fetchData)
}

注意:上面的 takeEvery 函數(shù)可以使用下面的寫法替換

function* watchFetchData() {
 
 while(true){
  yield take('FETCH_REQUESTED');
  yield fork(fetchData);
 }
}

takeLatest

在上面的例子中,takeEvery 允許多個 fetchData 實例同時啟動,在某個特定時刻,我們可以啟動一個新的 fetchData 任務(wù), 盡管之前還有一個或多個 fetchData 尚未結(jié)束

如果我們只想得到最新那個請求的響應(yīng)(例如,始終顯示最新版本的數(shù)據(jù)),我們可以使用 takeLatest 輔助函數(shù)

import { takeLatest } from 'redux-saga'

function* watchFetchData() {
 yield* takeLatest('FETCH_REQUESTED', fetchData)
}

和takeEvery不同,在任何時刻 takeLatest 只允許執(zhí)行一個 fetchData 任務(wù),并且這個任務(wù)是最后被啟動的那個,如果之前已經(jīng)有一個任務(wù)在執(zhí)行,那之前的這個任務(wù)會自動被取消

2、Effect Creators

redux-saga框架提供了很多創(chuàng)建effect的函數(shù),下面我們就來簡單的介紹下開發(fā)中最常用的幾種

  • take(pattern)
  • put(action)
  • call(fn, ...args)
  • fork(fn, ...args)
  • select(selector, ...args)

take(pattern)

take函數(shù)可以理解為監(jiān)聽未來的action,它創(chuàng)建了一個命令對象,告訴middleware等待一個特定的action, Generator會暫停,直到一個與pattern匹配的action被發(fā)起,才會繼續(xù)執(zhí)行下面的語句,也就是說,take是一個阻塞的 effect

用法:

function* watchFetchData() {
 while(true) {
 // 監(jiān)聽一個type為 'FETCH_REQUESTED' 的action的執(zhí)行,直到等到這個Action被觸發(fā),才會接著執(zhí)行下面的 yield fork(fetchData) 語句
  yield take('FETCH_REQUESTED');
  yield fork(fetchData);
 }
}

put(action)

put函數(shù)是用來發(fā)送action的 effect,你可以簡單的把它理解成為redux框架中的dispatch函數(shù),當(dāng)put一個action后,reducer中就會計算新的state并返回,注意: put 也是阻塞 effect

用法:

export function* toggleItemFlow() {
 let list = []
 // 發(fā)送一個type為 'UPDATE_DATA' 的Action,用來更新數(shù)據(jù),參數(shù)為 `data:list`
 yield put({
  type: actionTypes.UPDATE_DATA,
  data: list
 })
}

call(fn, ...args)

call函數(shù)你可以把它簡單的理解為就是可以調(diào)用其他函數(shù)的函數(shù),它命令 middleware 來調(diào)用fn 函數(shù), args為函數(shù)的參數(shù),注意:  fn 函數(shù)可以是一個 Generator 函數(shù),也可以是一個返回 Promise 的普通函數(shù),call 函數(shù)也是阻塞 effect

用法:

export const delay = ms => new Promise(resolve => setTimeout(resolve, ms))

export function* removeItem() {
 try {
 // 這里call 函數(shù)就調(diào)用了 delay 函數(shù),delay 函數(shù)為一個返回promise 的函數(shù)
 return yield call(delay, 500)
 } catch (err) {
 yield put({type: actionTypes.ERROR})
 }
}

fork(fn, ...args)

fork 函數(shù)和 call 函數(shù)很像,都是用來調(diào)用其他函數(shù)的,但是fork函數(shù)是非阻塞函數(shù),也就是說,程序執(zhí)行完 yield fork(fn, args) 這一行代碼后,會立即接著執(zhí)行下一行代碼語句,而不會等待fn函數(shù)返回結(jié)果后,在執(zhí)行下面的語句

用法:

import { fork } from 'redux-saga/effects'

export default function* rootSaga() {
 // 下面的四個 Generator 函數(shù)會一次執(zhí)行,不會阻塞執(zhí)行
 yield fork(addItemFlow)
 yield fork(removeItemFlow)
 yield fork(toggleItemFlow)
 yield fork(modifyItem)
}

select(selector, ...args)

select 函數(shù)是用來指示 middleware調(diào)用提供的選擇器獲取Store上的state數(shù)據(jù),你也可以簡單的把它理解為redux框架中獲取store上的 state數(shù)據(jù)一樣的功能 :store.getState()

用法:

export function* toggleItemFlow() {
  // 通過 select effect 來獲取 全局 state上的 `getTodoList` 中的 list
  let tempList = yield select(state => state.getTodoList.list)
}

一個具體的實例

**index.js **

import React from 'react';
import ReactDOM from 'react-dom';
import {createStore, applyMiddleware} from 'redux'
import createSagaMiddleware from 'redux-saga'

import rootSaga from './sagas'
import Counter from './Counter'
import rootReducer from './reducers'

const sagaMiddleware = createSagaMiddleware() // 創(chuàng)建了一個saga中間件實例

// 下邊這句話和下邊的兩行代碼創(chuàng)建store的方式是一樣的
// const store = createStore(reducers,applyMiddlecare(middlewares))

const createStoreWithMiddleware = applyMiddleware(middlewares)(createStore)
const store = createStoreWithMiddleware(rootReducer)

sagaMiddleware.run(rootSaga)

const action = type => store.dispatch({ type })

function render() {
 ReactDOM.render(
 <Counter
  value={store.getState()}
  onIncrement={() => action('INCREMENT')}
  onDecrement={() => action('DECREMENT')}
  onIncrementAsync={() => action('INCREMENT_ASYNC')} />,
 document.getElementById('root')
 )
}

render()

store.subscribe(render)

sagas.js

import { put, call, take,fork } from 'redux-saga/effects';
import { takeEvery, takeLatest } from 'redux-saga'

export const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

function* incrementAsync() {
 // 延遲 1s 在執(zhí)行 + 1操作
 yield call(delay, 1000);
 yield put({ type: 'INCREMENT' });
}

export default function* rootSaga() {
 // while(true){
 // yield take('INCREMENT_ASYNC');
 // yield fork(incrementAsync);
 // }

 // 下面的寫法與上面的寫法上等效
 yield* takeEvery("INCREMENT_ASYNC", incrementAsync)
}

reducer.js

export default function counter(state = 0, action) {
 switch (action.type) {
 case 'INCREMENT':
  return state + 1
 case 'DECREMENT':
  return state - 1
 case 'INCREMENT_ASYNC':
  return state
 default:
  return state
 }
}

從上面的代碼結(jié)構(gòu)可以看出,redux-saga的使用方式還是比較簡單的,相比較之前的redux框架的CounterApp,多了一個sagas的文件,reducers文件還是之前的使用方式

redux-saga基本用法總結(jié):

  • 使用 createSagaMiddleware 方法創(chuàng)建 saga 的 Middleware ,然后在創(chuàng)建的 redux 的 store 時,使用 applyMiddleware 函數(shù)將創(chuàng)建的 saga Middleware 實例綁定到 store 上,最后可以調(diào)用 saga Middleware 的 run 函數(shù)來執(zhí)行某個或者某些 Middleware 。
  • 在 saga 的 Middleware 中,可以使用 takeEvery 或者 takeLatest 等 API 來監(jiān)聽某個 action ,當(dāng)某個 action 觸發(fā)后, saga 可以使用 call 發(fā)起異步操作,操作完成后使用 put 函數(shù)觸發(fā) action ,同步更新 state ,從而完成整個 State 的更新。

ok,故事到這里就接近尾聲了,以上主要介紹了redux,react-redux和redux-saga目前redux全家桶主流的一些產(chǎn)品,接下來,主要會產(chǎn)出一下根據(jù)源碼,手寫一下redux和react-redux的輪子

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • React+Ant Design開發(fā)環(huán)境搭建的實現(xiàn)步驟

    React+Ant Design開發(fā)環(huán)境搭建的實現(xiàn)步驟

    這篇文章主要介紹了React+Ant Design開發(fā)環(huán)境搭建的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 詳解使用webpack+electron+reactJs開發(fā)windows桌面應(yīng)用

    詳解使用webpack+electron+reactJs開發(fā)windows桌面應(yīng)用

    這篇文章主要介紹了詳解使用webpack+electron+reactJs開發(fā)windows桌面應(yīng)用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02
  • 詳解react應(yīng)用中的DOM DIFF算法

    詳解react應(yīng)用中的DOM DIFF算法

    這篇文章主要介紹了react應(yīng)用中的DOM DIFF算法,幫助大家更好的理解和學(xué)習(xí)使用react,感興趣的朋友可以了解下
    2021-04-04
  • React Electron生成桌面應(yīng)用過程

    React Electron生成桌面應(yīng)用過程

    這篇文章主要介紹了React+Electron快速創(chuàng)建并打包成桌面應(yīng)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • React createElement方法使用原理分析介紹

    React createElement方法使用原理分析介紹

    這篇文章主要為大家介紹了React的createElement方法源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 減少react組件不必要的重新渲染實現(xiàn)方法

    減少react組件不必要的重新渲染實現(xiàn)方法

    這篇文章主要為大家介紹了減少react組件不必要的重新渲染實現(xiàn)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • React State與生命周期詳細(xì)介紹

    React State與生命周期詳細(xì)介紹

    React將組件(component)看成一個狀態(tài)機(State Machines),通過其內(nèi)部自定義的狀態(tài)(State)和生命周期(Lifecycle)實現(xiàn)并與用戶交互,維持組件的不同狀態(tài)
    2022-08-08
  • React配置代理方式(proxy)

    React配置代理方式(proxy)

    這篇文章主要介紹了React配置代理方式(proxy),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • React Native驗證碼倒計時工具類分享

    React Native驗證碼倒計時工具類分享

    這篇文章主要為大家分享了React Native驗證碼倒計時工具類,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • react map使用方法實例詳解

    react map使用方法實例詳解

    map()方法是在React中常用的數(shù)組處理方法之一,可以用于遍歷數(shù)組、生成組件列表以及進行數(shù)據(jù)轉(zhuǎn)換等操作,通過合理運用map()方法,可以更靈活地處理和展示數(shù)據(jù),下面給大家講解react map使用方法,感興趣的朋友一起看看吧
    2023-10-10

最新評論