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

詳解Redux的工作流程

 更新時間:2022年08月23日 14:37:49   作者:codeMak1r.小新  
這篇文章主要介紹了Redux的工作流程,redux是一個專門用于做狀態(tài)管理的JS庫,它可以在react、angular、vue等項(xiàng)目中,但基本與react配合使用,需要的朋友可以參考下

(當(dāng)然不是這張圖)

Redux理解

redux是什么

  • redux是一個專門用于做狀態(tài)管理的JS庫(不是react插件庫);
  • 它可以在react、angular、vue等項(xiàng)目中,但基本與react配合使用;
  • 作用:集中式管理react應(yīng)用中多個組件共享的狀態(tài)。

什么情況下需要使用redux?

  • 某個組件的狀態(tài),需要讓其他組件可以隨時拿到(共享);
  • 一個組件需要改變另一個組件的狀態(tài)(通信);
  • 總體原則:能不用就不用,如果不用比較吃力才考慮使用。

redux工作流程??圖

action

  • 動作的對象
  • 包含兩個屬性:
    • type:標(biāo)識屬性,值為字符串,唯一,必要屬性;
    • data:數(shù)據(jù)屬性,值類型任意,可選屬性。
  • 例子:{ type:‘ADD_STUDENT’, data:{name: ‘tom’,age: 18} }

reducer

  • 用于初始化狀態(tài)、加工狀態(tài);
  • 加工時,根據(jù)舊的 state 和 action,產(chǎn)生新的 state 的純函數(shù);
  • 初始化時,previousState 為 undefined。

store

  • 將state 、action 、reducer聯(lián)系在一起的對象;

  • 如何得到此對象?

如何得到此對象?

import { createStore } from 'redux'
//
import reducer from './reducers'
//
const store = createStore(reducer)

3.此對象的功能?

  • getState():得到 state;
  • dispatch(action):分發(fā) action,觸發(fā) reducer 調(diào)用,產(chǎn)生新的 state;
  • subscribe(listener):注冊監(jiān)聽,當(dāng)產(chǎn)生了新的 state 時,自動調(diào)用。

select選擇框內(nèi)有三個數(shù)組1、2、3可選,選擇1后點(diǎn)擊“加”即和加1;
第三個按鈕為和為奇數(shù)時,則加;和為偶數(shù)時,則不變;
最后的“異步加”則是用setTimeout模擬了一個異步環(huán)境,點(diǎn)擊“異步加”等待0.5s再加。

求和案例——純react版

項(xiàng)目目錄:

src
├─App.jsx
├─index.js
├─components
|     ├─Count
|     |   └index.jsx
public
└index.html

使用create-react-app創(chuàng)建腳手架項(xiàng)目,項(xiàng)目目錄如上所示。

純react版是通過本組件的state獲取數(shù)據(jù),在此不過多贅述。
歡迎訂閱本專欄【React–從基礎(chǔ)到實(shí)戰(zhàn)】學(xué)習(xí)react知識,持續(xù)更新中!

App.jsx

import React, { Component } from 'react'
import Count from './components/Count'

export default class App extends Component {
  render() {
    return (
      <div>
        <Count />
      </div>
    )
  }
}

src/component/Count/index.jsx

import React, { Component } from 'react'

export default class Count extends Component {

  state = { count: 0 }

  // 加法
  increment = () => {
    const { value } = this.selectedNumber
    const { count } = this.state
    this.setState({ count: count + parseInt(value) });
  }
  // 減法
  decrement = () => {
    const { value } = this.selectedNumber
    const { count } = this.state
    this.setState({ count: count - value });
  }
  // 和為奇數(shù)時,加
  incrementIfOdd = () => {
    const { value } = this.selectedNumber
    const { count } = this.state
    // 除以2取余數(shù),余數(shù)為0代表和為偶數(shù),不加;余數(shù)不為0,代表和為奇數(shù),加
    if (count % 2 !== 0) {
      this.setState({ count: count + parseInt(value) });
    }
  }
  // 異步加
  incrementAsync = () => {
    const { value } = this.selectedNumber
    const { count } = this.state
    setTimeout(() => {
      this.setState({ count: count + parseInt(value) });
    }, 500)
  }

  render() {
    return (
      <div>
        <h1>當(dāng)前求和為:{this.state.count}</h1>
        <select ref={currentNode => { this.selectedNumber = currentNode }}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>&nbsp;&nbsp;&nbsp;
        <button onClick={this.increment}>加</button>&nbsp;
        <button onClick={this.decrement}>減</button>&nbsp;
        <button onClick={this.incrementIfOdd}>和為奇數(shù)時,加</button>&nbsp;
        <button onClick={this.incrementAsync}>異步加</button>
      </div>
    )
  }
}

求和案例——redux精簡版

為了讓大家更好的理解redux基本原理,我們先僅使用少數(shù)的api,用過一個精簡版的redux去完成這個求和案例,最后我們會用完整版的redux去完成這個求和案例。學(xué)東西嘛,得循序漸進(jìn),不能一口吃成大胖子不是?

首先,我們需要下載redux:

npm install redux
或
yarn add redux

根據(jù)原理圖,我們必不可少的肯定是需要store這個對象,以及reducer這個函數(shù)的。

store對象負(fù)責(zé)存儲state,reducer負(fù)責(zé)初始化和加工state,都是必不可少的。

1、創(chuàng)建store.js

/* 
  該文件專門用于暴露一個store對象,整個應(yīng)用只有一個store對象
*/
// 引入createStore,專門用于創(chuàng)建redux中最為核心的store對象
import { legacy_createStore as createStore } from 'redux';
// 引入為Count組件服務(wù)的reducer
import countReducer from './count_reducer'
// 暴露store
export default createStore(countReducer)

2、創(chuàng)建count_reducer.js

/* 
  1.該文件用于創(chuàng)建一個為Count組件服務(wù)的reducer函數(shù)
  2.reducer函數(shù)會接收到兩個參數(shù),分別為之前的狀態(tài)(prevState)和動作對象(action)
*/
// 初始化state,prevState=initState含義是:給形參prevState賦初始值
const initState = 0
export default function countReducer(prevState = initState, action) {
  console.log(prevState, action)
  // 從action對象中獲取type、data
  const { type, data } = action
  // 根據(jù)type的值決定如何加工數(shù)據(jù)
  switch (type) {
    case 'increment':
      return prevState + data;
    case 'decrement':
      return prevState - data;
    default:
      return prevState
  }
}

3、回到Count組件中,我們先試著獲取到store中存儲的數(shù)據(jù)。

//  引入store,用于獲取redux中保存的狀態(tài)
import store from '../../redux/store'
···
render() {
    return (
      <div>
      // <h1>當(dāng)前求和為:{this.state.count}</h1>
        <h1>當(dāng)前求和為:{store.getState()}</h1>
···

現(xiàn)在我們把狀態(tài)(state)交給redux管理了,當(dāng)然就不需要在Count組件中初始化狀態(tài)了,也就不需要再到this.state中結(jié)構(gòu)賦值count變量了。

我們只需要調(diào)用redux的api:store.getState()就能夠拿到存儲在store中的狀態(tài)。

打開界面一看:

果然是拿到了狀態(tài)state,那么我們就著手依次進(jìn)行計(jì)算操作了~

首先是,點(diǎn)擊“加”按鈕,觸發(fā)this.increment方法,我們在方法內(nèi)部只需要調(diào)用redux的api:dispatch()即可。

// 加法
  increment = () => {
    const { value } = this.selectedNumber
    store.dispatch({ type: 'increment', data: parseInt(value) })
  }

我們通過調(diào)用dispatch()方法,傳入一個我們自己定義的action動作對象,進(jìn)行“加”的動作,這個動作對象會由store傳給reducer函數(shù),函數(shù)內(nèi)部判斷type值為‘increment’,那么就會對這個‘和’進(jìn)行“加”的動作

代碼實(shí)現(xiàn)完了,我們看一下效果:

完?duì)僮樱@怎么沒加上去呢?

我們在count_reducer中console一下,找找原因,

打開控制臺,我們發(fā)現(xiàn)狀態(tài)是在跟隨我們的點(diǎn)擊隨之改變的,但是頁面并沒有同步這個狀態(tài)的改變。換句話說,也就是狀態(tài)改變了,頁面并沒有隨著狀態(tài)的改變而重新渲染。在之前的純react版本中,我們是通過this.setState()進(jìn)行狀態(tài)更新的,我們都知道react中,setState可以驅(qū)動視圖更新,但是我們現(xiàn)在并不在組件的state中管理狀態(tài),而是通過redux進(jìn)行狀態(tài)的管理,所以才會導(dǎo)致頁面沒有更新。

我們需要手動監(jiān)測redux中store狀態(tài),當(dāng)狀態(tài)發(fā)生變化時,我們自己去手動調(diào)用render,就可以解決頁面不更新的問題。

componentDidMount() {
  // 監(jiān)測redux中狀態(tài)的變化,只要變化,就調(diào)用render
  store.subscribe(() => {
    this.setState({})
  })
}

我們可以使用這個api:store.subscribe()這個函數(shù)的參數(shù)接受一個回調(diào)函數(shù),只要redux中的任何狀態(tài)發(fā)生了改變,都會調(diào)用這個回調(diào)函數(shù)。我們可以在這個回調(diào)函數(shù)內(nèi)部手動調(diào)用this.setState({}),只要這么調(diào)用了,就會自動重新render,這樣就可以實(shí)現(xiàn)頁面的更新了。

Count組件源碼:

import React, { Component } from 'react'
//  引入store,用于獲取redux中保存的狀態(tài)
import store from '../../redux/store'

export default class Count extends Component {

  componentDidMount() {
    // 監(jiān)測redux中狀態(tài)的變化,只要變化,就調(diào)用render
    store.subscribe(() => {
      this.setState({})
    })
  }

  // 加法
  increment = () => {
    const { value } = this.selectedNumber
    store.dispatch({ type: 'increment', data: value * 1 })
  }
  // 減法
  decrement = () => {
    const { value } = this.selectedNumber
    store.dispatch({ type: 'decrement', data: value * 1 })
  }
  // 和為奇數(shù)時,加
  incrementIfOdd = () => {
    const { value } = this.selectedNumber
    const count = store.getState()
    // 除以2取余數(shù),余數(shù)為0代表和為偶數(shù),不加;余數(shù)不為0,代表和為奇數(shù),加
    if (count % 2 !== 0) {
      store.dispatch({ type: 'increment', data: value * 1 })
    }
  }
  // 異步加
  incrementAsync = () => {
    const { value } = this.selectedNumber
    setTimeout(() => {
      store.dispatch({ type: 'increment', data: value * 1 })
    }, 500)
  }

  render() {
    return (
      <div>
        <h1>當(dāng)前求和為:{store.getState()}</h1>
        <select ref={currentNode => { this.selectedNumber = currentNode }}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>&nbsp;&nbsp;&nbsp;
        <button onClick={this.increment}>加</button>&nbsp;
        <button onClick={this.decrement}>減</button>&nbsp;
        <button onClick={this.incrementIfOdd}>和為奇數(shù)時,加</button>&nbsp;
        <button onClick={this.incrementAsync}>異步加</button>
      </div>
    )
  }
}

redux精簡版總結(jié):

去除Count組件自身狀態(tài)state;

src下建立:

/src/redux/store.js

/src/reudx/count_reducer.js

store.js

引入redux中的legacy_createStore函數(shù),創(chuàng)建一個store;

legacy_createStore調(diào)用時要傳入一個為其服務(wù)的reducer;

默認(rèn)暴露store對象

count_reducer.js

reducer本質(zhì)是一個函數(shù),接收:preState,action作為參數(shù),返回加工后的狀態(tài);

reducer有兩個作用:初始化狀態(tài),加工狀態(tài);

reducer被第一次調(diào)用,是store自動觸發(fā)的,傳遞的preState是undefined

狀態(tài)改變后手動調(diào)用setState()以達(dá)到頁面實(shí)時渲染的效果。

求和案例——redux完整版

在精簡版中,我們使用的action對象是我們自己手動傳入的action動作對象,但是redux有更好的api,來幫助我們自動創(chuàng)建action動作對象,不需要手動輸入。我們來看看redux完整版是怎么實(shí)現(xiàn)集中狀態(tài)管理的吧~

基于精簡版,我們還需要在redux文件夾下創(chuàng)建一個文件

/src/redux/count_action_creator.js,該文件專門用于為Count組件生成action動作對象。

count_action_creator.js

/* 
  該文件專門為Count組件生成action動作對象
*/
export const createIncrementAction = data => ({ type: 'increment', data })
// ({ type: 'increment', data }) 相當(dāng)于 { return { type: 'increment', data } }

export const createDecrementAction = data => ({ type: 'decrement', data })

在Count組件中引入文件以及暴露的函數(shù):

// 引入actionCreator,專門用于創(chuàng)建action對象
import {
  createIncrementAction,
  createDecrementAction
} from '../../redux/count_action_creator'

在所有需要使用dispatch分派action動作對象時,我們不再使用之前手打的action對象了,而是直接調(diào)用函數(shù),自動生成action對象。

例如,在點(diǎn)擊“加”按鈕方法中:

// 加法
increment = () => {
  const { value } = this.selectedNumber
  store.dispatch(createIncrementAction(value * 1))
}

以此類推,將所有方法內(nèi)手打的action對象更改為使用函數(shù)自動生成的action對象。

Count組件源碼:

import React, { Component } from 'react'
//  引入store,用于獲取redux中保存的狀態(tài)
import store from '../../redux/store'
// 引入actionCreator,專門用于創(chuàng)建action對象
import {
  createIncrementAction,
  createDecrementAction
} from '../../redux/count_action_creator'

export default class Count extends Component {

  componentDidMount() {
    // 監(jiān)測redux中狀態(tài)的變化,只要變化,就調(diào)用render
    store.subscribe(() => {
      this.setState({})
    })
  }

  // 加法
  increment = () => {
    const { value } = this.selectedNumber
    store.dispatch(createIncrementAction(value * 1))
  }
  // 減法
  decrement = () => {
    const { value } = this.selectedNumber
    store.dispatch(createDecrementAction(value * 1))
  }
  // 和為奇數(shù)時,加
  incrementIfOdd = () => {
    const { value } = this.selectedNumber
    const count = store.getState()
    // 除以2取余數(shù),余數(shù)為0代表和為偶數(shù),不加;余數(shù)不為0,代表和為奇數(shù),加
    if (count % 2 !== 0) {
      store.dispatch(createIncrementAction(value * 1))
    }
  }
  // 異步加
  incrementAsync = () => {
    const { value } = this.selectedNumber
    setTimeout(() => {
      store.dispatch(createIncrementAction(value * 1))
    }, 500)
  }

  render() {
    return (
      <div>
        <h1>當(dāng)前求和為:{store.getState()}</h1>
        <select ref={currentNode => { this.selectedNumber = currentNode }}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>&nbsp;&nbsp;&nbsp;
        <button onClick={this.increment}>加</button>&nbsp;
        <button onClick={this.decrement}>減</button>&nbsp;
        <button onClick={this.incrementIfOdd}>和為奇數(shù)時,加</button>&nbsp;
        <button onClick={this.incrementAsync}>異步加</button>
      </div>
    )
  }
}

這樣一來,基本的redux完整版就已經(jīng)寫完了;但是還有一個可優(yōu)化的空間,我們在各個文件中都寫了’increment’和’decrement’字符串,這會帶來一些問題:

  • 字符串在IDE中沒有變量提示,容易拼寫錯誤;
  • 不便于維護(hù)和管理,一旦要更換字符串名稱,需要到各個文件中都去更改一次; redux完整版(優(yōu)化)

于是我們可以再創(chuàng)建一個js文件,用于常量的管理(常量維護(hù)):

/src/redux/constant.js

/* 
  該模塊是用于定義action對象中type類型的常量模塊
  便于管理的同時避免程序員單詞拼寫出錯
*/
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'

更改,count_action_creator.js

import { INCREMENT, DECREMENT } from './constant'
export const createIncrementAction = data => ({ type: INCREMENT, data })
export const createDecrementAction = data => ({ type: DECREMENT, data })

更改,count_reducer.js

+ import { INCREMENT, DECREMENT } from './constant'
const initState = 0
export default function countReducer(prevState = initState, action) {
  console.log(prevState, action)
  const { type, data } = action
  switch (type) {
  - case 'increment':
  + case INCREMENT:
      return prevState + data;
  - case 'decrement':
  + case DECREMENT:
      return prevState - data;
    default:
      return prevState
  }
}

如此一來,有利于后續(xù)項(xiàng)目越來越大的時候,進(jìn)行變量名的管理與維護(hù);而且,書寫字符串是沒有提示的,但是向這樣引入變量,書寫變量是有提示的,變量書寫錯誤的話,IDE還有相應(yīng)的錯誤提示,更加規(guī)范。

redux完整版總結(jié):

  • count_action.js 專門用于創(chuàng)建action動作對象;
  • constant.js 放置由于編碼疏忽可能寫錯的action中的type。

到此這篇關(guān)于Redux的工作流程的文章就介紹到這了,更多相關(guān)Redux工作流程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論