redux 和 mobx 調研結果- mobx

調研方向

  • 設計思想/基本用法/生態環境/性能優化
  • 總結

 

設計思想

mobx 的設計思想我總結以後,主要有如下兩點:javascript

  1. 函數響應式編程;
  2. 任何源自應用狀態的東西都應該自動地得到;

mobx 不一樣於 redux 的單一數據源的統一管理,它能夠有多個 store, 爲了便於維護 ,每個 store 都是一個類,這樣便於維護和擴展;php

同時,爲了使數據能夠自動更新,使用了響應式編程(異步數據流), 它使用了觀察者模式和 裝飾器模式,將 state 包裹成observable; 當state 有改變時(本身改變或是 action 觸發), 就會相應的去更新由這個state 推導出來的 computed value 以及 reaction;(數據的更新主要由裝飾器模式中的對類的修改 );vue

它的工做流大體是這樣子:java

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

基本用法

mobx 與redux 同樣也是單向數據流,核心概念是 state,computed value,reaction,action 等。它們的大概功能爲:react

  • state: 包裹爲 observable 的 的數據;編程

  • computed values: 從當前 state 中計算出的值,相似與 vue 中的computed;redux

  • reactions: 是當 state 改變時須要自動發生的反作用。好比打印到控制檯、網絡請求、遞增地更新 React 組件樹以修補 DOM 等等;不會產生值,常見 api 有 autorun, reaction, observe (針對性觀察新舊值)等;後端

  • action: 是一段能夠改變狀態的代碼。用戶事件、後端數據推送、預約事件、等等。一般使用 action 統一對 state 修改,而不是對自身修改;api

這樣聽可能有一點抽象, 以表格爲例:在電子表格中,有值的單元格都是 observable state;公式和圖標是可從數據單元格和其餘公式推導出的computed value;在屏幕上繪製數據單元格、公式的輸出結果就是一個 reactions;對數據單元格或公式的修改就是一次action;性能優化

這裏用一個栗子介紹:

class Person {
	// 定義狀態
  [@observable] firstName = "huang";
  [@observable] lastName = "yuan";
  [@observable] nickName;
  
  @computed get fullName() {
    return this.firstName + " " + this.lastName;
  }
	@action.bound
    increment() {
	        this.firstName = "zhang";
    }
}
decorate{
}
const coolGirl = new Person();

// reactions:打印日誌
autorun(() => {
  console.log(
    person.nickName ? person.nickName : person.fullName
  )
});

const ProfileView = observer(props => {
  if (props.person.nickName)
    return <div>{props.person.nickName}</div>
  else
    return <div>{props.person.fullName}</div>
});

// action
setTimeout(() => coolGirl.nickName = "yuanzhendashi", 5000);
setIimeout(coolGirl.increment, 1000);

React.render(<ProfileView person={coolGirl} />), document.body);

這是一個很簡單的栗子,展現了mobx 的基本使用,主要分爲這幾個步驟;

  • 定義 state;將 Person 的 firstName,lastName,nickName observable 化;
  • 註冊 computed value: 經過現有的 observable 變化時能夠獲得 fullName;
  • 註冊反應 reactions: autorun; 在初始化時和 nickName 發生變化時,會打印日誌;
  • 在觸發 action 的時刻, 修改了firstName;

這是一個最簡單的例子,展現了 Mobx 主要的代碼組成:定義狀態 -> 註冊反應 -> 修改狀態 -> 執行反應。

 

生態環境

主要跟你們說說,在與現有的技術棧或應用結合時,Mobx 生態有哪些最佳實踐和優質的庫。

  • 裝飾器語法支持:create-react-app 目前尚未內置的裝飾器支持。要解決這個問題,要使用 eject 命令;推薦使用mobx 內置的工具 decorate 來對類和對象進行裝飾,而這個不須要啓用裝飾器語法;
  • 與react 結合使用:可引入 mobx-react,自動綁定並更新 React 視圖模板。
  • 狀態管理: 可引入 mobx-state-tree,同時具有 immutable 數據的各類管理優點。

與react 結合使用擴展

當與 React 結合時,使用了mobox-react 庫來處理 state 變化和view 更新的綁定在用法上,主要分爲四個步驟:

一、 使用Provide組件用來包裹最外層組件節點,傳入 store 經過 context 傳遞給後代組件;

2 . 經過 @observer 將 React 組件轉化成響應式組件;mobx 用 autorun 包裝了組件的 render 函數以確保任何組件渲染中使用的數據變化時均可以強制刷新組件;

  1. 使用 @inject 給組件注入其須要的store,放置於 props 上;

  2. 觀察並使用store 中的observable 數據

以下面代碼

// 以 context 的形式傳入store
import { Provider } from 'mobx-react' 
<Provider store={coolGirl}>
		<ProfileView/>
</Provider>


// 使用狀態
import * as React from 'react'
import { inject, observer } from 'mobx-react'

@inject('store') // 若是是以 context 傳入的必需要 @inject,不然不須要。
@observer
**export de**fault class ProfileView extends React.Component { 
	render () { 
	return ( <div> 個人姓名:{this.props.store.fullName} </div> ) 
	}
}

能夠看出,使用起來很是簡便;

 

性能優化

  • 儘量多地使用小組件;@observer 組件會追蹤 render 方法中全部的可觀測的值,當任何一個值變化的時候,都會從新渲染,因此組件越小,從新渲染的變化就越小。

  • 在專用的組件中渲染列表;

  • 晚一點使用間接引用值;使用 mobx-react 時,推薦儘量晚的使用間接引用值。 這是由於當使用 observable 間接引用值時 MobX 會自動從新渲染組件。 若是間接引用值發生在組件樹的層級越深,那麼須要從新渲染的組件就越少;

    快的: <DisplayName person={person} /> 慢的: <DisplayName name={person.name} />

  • 對於autorun 和reaction,每次變化的準備時間和結束時間爲0.5 ~ 1ms。因此,可能不適合跟蹤頻繁變化的狀態;

  • 減小渲染次數: 使用 action 觸發狀態更新;

vi設計http://www.maiqicn.com 辦公資源網站大全https://www.wode007.com

發展趨勢

內存/mobx-state-tree

 

總結

綜上,使用mobx-react , 會有這些優缺點:

  • 優勢:上手簡單, 代碼量少,響應快速,生態環境不錯,正在茁壯成長;
  • 缺點: 因爲store "分而治之",當組件變多,應用變複雜時,團隊協做會變困難,狀態管路容易出現問題,代碼難以維護;
相關文章
相關標籤/搜索