最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Redux的工作流程

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

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

Redux理解

redux是什么

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

什么情況下需要使用redux?

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

redux工作流程??圖

action

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

reducer

  • 用于初始化狀態(tài)、加工狀態(tài);
  • 加工時(shí),根據(jù)舊的 state 和 action,產(chǎn)生新的 state 的純函數(shù);
  • 初始化時(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 時(shí),自動調(diào)用。

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

求和案例——純r(jià)eact版

項(xiàng)目目錄:

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

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

純r(jià)eact版是通過本組件的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ù)時(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ù)時(shí),加</button>&nbsp;
        <button onClick={this.incrementAsync}>異步加</button>
      </div>
    )
  }
}

求和案例——redux精簡版

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

首先,我們需要下載redux:

npm install redux
或
yarn add redux

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

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

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

/* 
  該文件專門用于暴露一個(gè)store對象,整個(gè)應(yīng)用只有一個(gè)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)建一個(gè)為Count組件服務(wù)的reducer函數(shù)
  2.reducer函數(shù)會接收到兩個(gè)參數(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()方法,傳入一個(gè)我們自己定義的action動作對象,進(jìn)行“加”的動作,這個(gè)動作對象會由store傳給reducer函數(shù),函數(shù)內(nèi)部判斷type值為‘increment’,那么就會對這個(gè)‘和’進(jìn)行“加”的動作

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

完?duì)僮?,這怎么沒加上去呢?

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

打開控制臺,我們發(fā)現(xiàn)狀態(tài)是在跟隨我們的點(diǎn)擊隨之改變的,但是頁面并沒有同步這個(gè)狀態(tài)的改變。換句話說,也就是狀態(tài)改變了,頁面并沒有隨著狀態(tài)的改變而重新渲染。在之前的純r(jià)eact版本中,我們是通過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ā)生變化時(shí),我們自己去手動調(diào)用render,就可以解決頁面不更新的問題。

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

我們可以使用這個(gè)api:store.subscribe()這個(gè)函數(shù)的參數(shù)接受一個(gè)回調(diào)函數(shù),只要redux中的任何狀態(tài)發(fā)生了改變,都會調(diào)用這個(gè)回調(diào)函數(shù)。我們可以在這個(gè)回調(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ù)時(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ù)時(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)建一個(gè)store;

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

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

count_reducer.js

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

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

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

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

求和案例——redux完整版

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

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

/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動作對象時(shí),我們不再使用之前手打的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ù)時(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ù)時(shí),加</button>&nbsp;
        <button onClick={this.incrementAsync}>異步加</button>
      </div>
    )
  }
}

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

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

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

/src/redux/constant.js

/* 
  該模塊是用于定義action對象中type類型的常量模塊
  便于管理的同時(shí)避免程序員單詞拼寫出錯
*/
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)目越來越大的時(shí)候,進(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)文章

  • React日期時(shí)間顯示組件的封裝方法

    React日期時(shí)間顯示組件的封裝方法

    這篇文章主要為大家詳細(xì)介紹了React日期時(shí)間顯示組件的封裝方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • React中的useEffect useLayoutEffect到底怎么用

    React中的useEffect useLayoutEffect到底怎么用

    這篇文章主要介紹了React中的useEffect useLayoutEffect具體使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • 解決react中useState狀態(tài)異步更新的問題

    解決react中useState狀態(tài)異步更新的問題

    本文主要介紹了react中useState狀態(tài)異步更新的問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • React Router6.x路由表封裝的兩種寫法

    React Router6.x路由表封裝的兩種寫法

    本文主要介紹了React Router6.x路由表封裝的兩種寫法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • React常見跨窗口通信方式實(shí)例詳解

    React常見跨窗口通信方式實(shí)例詳解

    這篇文章主要為大家介紹了React常見跨窗口通信方式實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • React hooks如何清除定時(shí)器并驗(yàn)證效果

    React hooks如何清除定時(shí)器并驗(yàn)證效果

    在React中,通過自定義Hook useTimeHook實(shí)現(xiàn)定時(shí)器的啟動與清除,在App組件中使用Clock組件展示當(dāng)前時(shí)間,利用useEffect鉤子在組件掛載時(shí)啟動定時(shí)器,同時(shí)確保組件卸載時(shí)清除定時(shí)器,避免內(nèi)存泄露,這種方式簡化了狀態(tài)管理和副作用的處理
    2024-10-10
  • React中DOM事件和狀態(tài)介紹

    React中DOM事件和狀態(tài)介紹

    這篇文章主要介紹了React中DOM事件和狀態(tài)介紹,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下
    2022-08-08
  • react實(shí)現(xiàn)一個(gè)優(yōu)雅的圖片占位模塊組件詳解

    react實(shí)現(xiàn)一個(gè)優(yōu)雅的圖片占位模塊組件詳解

    這篇文章主要給大家介紹了關(guān)于react如何實(shí)現(xiàn)一個(gè)還算優(yōu)雅的占位模塊圖片組件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • React+EggJs實(shí)現(xiàn)斷點(diǎn)續(xù)傳的示例代碼

    React+EggJs實(shí)現(xiàn)斷點(diǎn)續(xù)傳的示例代碼

    這篇文章主要介紹了React+EggJs實(shí)現(xiàn)斷點(diǎn)續(xù)傳的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • React如何使用Portal實(shí)現(xiàn)跨層級DOM渲染

    React如何使用Portal實(shí)現(xiàn)跨層級DOM渲染

    Portal 就像是一個(gè)“傳送門”,能讓你把組件里的元素“傳送到”其他 DOM 節(jié)點(diǎn)下面去渲染,下面小編就來和大家簡單介紹一下具體的使用方法吧
    2025-04-04

最新評論

平泉县| 赤峰市| 汨罗市| 山东省| 项城市| 团风县| 阳高县| 云阳县| 宝山区| 三亚市| 佛学| 兴仁县| 和平区| 青阳县| 贵港市| 墨竹工卡县| 上蔡县| 儋州市| 广水市| 义马市| 庆安县| 如东县| 新巴尔虎左旗| 海丰县| 纳雍县| 保靖县| 招远市| 安图县| 台中市| 日土县| 扶绥县| 故城县| 上林县| 阳城县| 新田县| 柳林县| 旺苍县| 浦城县| 平顺县| 佛山市| 永安市|