redux和dva


實習的時候,公司使用的是react,react說實話生態學的還不是很完善,就暫時先不做跟react相關的博客,等以后學好了react全家桶之后,專門再總結一下react的內容

這兩天看了公司的alita和dva,具體項目還沒上手,但是對dva很感興趣,一方面因為dva名字的由來,另一方面剛好在看redux的內容。

在講redux的時候,不得不把vuex拿出來講講,說實話,vuex很久之前學的了,vue是我前端框架第一次接觸的,vue的方便性也讓我很喜愛,但是身為一個前端攻城獅怎么能不學其他框架呢,趁着在公司實習的日子里,把react的學習提上日程

扯遠了,回到redux和vuex中。redux是一個狀態數據的管理庫,它可以用在react,也可以用在vue中,但是vue自己有一個vuex,兼容性更好,所以更大多數redux用在react的項目中。

學習vuex的時候,與現在的redux做對比,很清晰能比較出來,vuex比redux簡單

下圖是vuex的工作流程原理

 

 

 

VueX是數據管理框架,在之前我們vue里面的數據是data,父子組件,provide等等傳遞 在vue工程里面,數據就不是組件級別的創建,而是頁面級別的創建了

 

 

 VueX創建了全局的倉庫,在vuex的state中,存放在全局的數據。我們使用vuex提供的store對象的state屬性,來獲取全局的數據

export default{
  name:'Home',
  computed:{
    myName(){
      return this.$store.state.name;
    }
  }
}

我們如何修改全局的數據?Vuex不允許我們直接修改全局的數據

因此我們要 調用$store里面一個方法叫做dispatch,他去派發一個action,這個action的名字叫做change 在createStore里就有一個action接收派發而來的change,執行這個change方法。在這個方法中提交一個commit觸發一個mutation,在mutations里面接收觸發而來方法並執行,在該方法中我們就可以修改數據

vuex的工作流程就是,組件之間使用dispatch去派發一個action,vuex中主要有三個屬性action,commit,state用來操作管理數據。

actions感知到組件所派發的action,執行action對應參數的方法,提交一個commit去觸發mutation,mutation中執行收到的commit的參數方法。從而修改state數據,而這個state數據就是全局的數據倉庫

 

 

 在最近的學習中,我接觸到了redux,說實話,redux復雜程度高於vuex。

react整個應用中會存在很多個組件,每個組件的state是由自身進行管理,包括組件定義自身的state、組件之間的通信通過props傳遞、使用Context實現數據共享

將所有的狀態進行集中管理,當需要更新狀態的時候,僅需要對這個管理集中處理,而不用去關心狀態是如何分發到每一個組件內部的

redux就是一個實現上述集中管理的容器,遵循三大基本原則:

  • 單一數據源
  • state 是只讀的
  • 使用純函數來執行修改

redux要求我們把數據都放在 store公共存儲空間

一個組件改變了 store 里的數據內容,其他組件就能感知到 store的變化,再來取數據,從而間接的實現了這些數據傳遞的功能

 

 

 React Components (組件)需要獲取一些數據, 然后它就告知 Store 需要獲取數據,這就是 Action Creactor , Store 接收到之后去 Reducer 查一下, Reducer 會告訴 Store 應該給這個組件什么數據

如何使用?

創建一個store

import { createStore } from 'redux' // 引入redux 
const store = createStore() // 創建數據的公共存儲區域

還需要創建一個記錄本去輔助管理數據,也就是reduecer,本質就是一個函數,接收兩個參數state,action,返回state

// 設置默認值 
const initialState = { 
  counter: 0 
} 
 
const reducer = (state = initialState, action) => { 
} 

將記錄本傳遞給store,兩者建立連接,獲取store里面的數據,則通過store.getState()來獲取當前state

const store = createStore(reducer) 
store.getState()

那么如何更改store中的數據呢?

是通過dispatch來派發action,通常action中都會有type屬性,還有傳入的更改數據。

type屬性代表這個action所要做的操作

store.dispatch({ 
  type: "ADD_NUMBER", 
  number: 5 
}) 

ruducer中處理所要進行操作,使用swich去接收不同action所代表的操作方法

const reducer = (state = initialState, action) => { 
  switch (action.type) { 
    case "INCREMENT": 
      return {...state, counter: state.counter + 1}; 
    case "DECREMENT": 
      return {...state, counter: state.counter - 1}; 
    case "ADD_NUMBER": 
      return {...state, counter: state.counter + action.number} 
    default:  
      return state; 
  } 
} 

注意,reducer是一個純函數,不需要直接修改state

這樣派發action之后,既可以通過store.subscribe監聽store的變化,如下:

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

小結

  • createStore可以幫助創建 store
  • store.dispatch 幫助派發 action , action 會傳遞給 store
  • store.getState 這個方法可以幫助獲取 store 里邊所有的數據內容
  • store.subscrible 方法訂閱 store 的改變,只要 store 發生改變, store.subscrible 這個函數接收的這個回調函數就會被執行

在React項目中,會搭配react-redux進行使用

何為react-redux?

如下圖

 

 

在react-redux中,我們將UI組件去除掉redux的操作,將redux的操作全部放在容器組件身上

容器組件向redux進行數據獲取和更改,通過props將數據傳遞給UI組件,UI組件也通過props告知容器組件要對redux中的數據進行何樣的操作

容器組件用以專門向reduxi請求修改狀態,存在containers文件夾里面

UI組件無法向redux去修改,存在component文件夾里面

connet是一個函數,這個函數調用的返回值依舊是一個函數 ,返回值的函數讓容器組件與UI組件進行關聯,從而通過props進行組件間的通信。

const CountContainer=connect()(CountUI)

connect在第一次調用的時候要傳入兩個參數,傳入的兩個參數必須是函數 一個是redux中所保存的狀態,另一個就是操作狀態的方法。簡寫如下

function a(){
    return {n:900}
}

function b(){
    return {jia:(num)=>{dispatch({
  type: "ADD_NUMBER", number: 5
})}}
}

export default connect(a,b)(CountUI)

a函數返回的對象key作為UI組件的props的key,value作為UI組件的props的value,以供UI組件接收到state

b函數返回的對象實際上向redux派生一個action,告知redux對state中的數據進行何種操作

容器組件的兩個方法:mapStateToProps和mapDispatchToProps.

這是官方給的名稱,為了好理解上面的代碼使用a,b簡述。實際使用以官方文檔為主

export default connect(mapStateToProps,mapDispatchToProps)(CountUI)

回到今天所學習到的新框架——dva

dva 好像就是redux的一些輕量級應用整合,簡化了API,讓開發更方便,但果然這是我自己的理解。

核心概念

  • State:一個對象,保存整個應用狀態
  • View:React 組件構成的視圖層
  • Action:一個對象,描述事件
  • connect 方法:一個函數,綁定 State 到 View
  • dispatch 方法:一個函數,發送 Action 到 State

不難發現,其本質和redux一樣,只不過dva讓redux的操作更加的方便簡潔,提高了我們的開發效率。

Action 是用來描述 UI 層事件的一個對象。

connect 方法返回的也是一個 React 組件,也是稱為容器組件。因為它是原始 UI 組件的容器,即在外面包了一層 State。

connect 方法傳入的第一個參數是 mapStateToProps 函數,mapStateToProps 函數會返回一個對象,用於建立 State 到 Props 的映射關系。

dispatch 是一個函數方法,用來將 Action 發送給 State。

dispatch 方法從哪里來?被 connect 的 Component 會自動在 props 中擁有 dispatch 方法。

其實dva內容和react-redux是一樣的原理,只不過為了開發速度,dva封裝的API使得操作redux更為便捷

dva中有model對象,這個對象是我第一次遇到的,在這個對象中,封裝這對redux中的各種操作

model最簡結構

export default {
  namespace: 'count',
  state: 0,
  reducers: {
    add(state) {
      return state + 1;
    },
  },
  effects: {
    *addAfter1Second(action, { call, put }) {
      yield call(delay, 1000);
      yield put({ type: 'add' });
    },
  },
};

Model 對象的屬性

  • namespace: 當前 Model 的名稱。整個應用的 State,由多個小的 Model 的 State 以 namespace 為 key 合成
  • state: 該 Model 當前的狀態。數據保存在這里,直接決定了視圖層的輸出
  • reducers: Action 處理器,處理同步動作,用來算出最新的 State
  • effects:Action 處理器,處理異步動作

Reducer

Reducer 是 Action 處理器,用來處理同步操作,可以看做是 state 的計算器。它的作用是根據 Action,從上一個 State 算出當前 State。

Effect

Action 處理器,處理異步動作,基於 Redux-saga 實現。Effect 指的是副作用。根據函數式編程,計算以外的操作都屬於 Effect,典型的就是 I/O 操作、數據庫讀寫。

Generator 函數

Effect 是一個 Generator 函數,內部使用 yield 關鍵字,標識每一步的操作(不管是異步或同步)。

call 和 put

dva 提供多個 effect 函數內部的處理函數,比較常用的是 call 和 put

    • call:執行異步函數
    • put:發出一個 Action,類似於 dispatch

我們約定當 src/models 下存在 dva 的 models 文件時,會被自動加載到項目中。 即約定了存在即生效,因此我們約定僅在這個文件夾下存放 dva 的 models 文件,雖然存放其他的文件會被框架自動過濾忽略,但是在這個目錄存放其他文件會增加理解的心智負擔,建議不要存放無關的文件。且為了管理方便,一般將文件名和 models 的 namespace 一一對應,不僅可以直觀的找到相應的 models ,而且能夠保證不會存在 models 沖突的問題,因為文件系統本身就不允許同名文件。

時間不早,先休息,后面將會針對dva操作redux的具體進行總結,在這個總結中我們可以很直白的看出dva與redux操作上的簡易程度

宣傳下自己的網站mishi-blog.com

尚在襁褓中的一個網站。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM