一個簡潔且強大的狀態管理庫 - iFlow

前言

以React為主的開發過程中,用過主流的兩大狀態管理工具Redux和Mobx。但在我使用它們時,逐漸地感覺到了一些不太好的地方:Redux使用過程有點冗余和拖沓,而盡管Redux也有中間件,但Redux帶來的收益和它官方說的一樣:僅僅只是一個純的狀態容器而不是狀態管理;而基于Observable的狀態管理庫Mobx則侵入性強,且丟失狀態類型的原始性(被Observable實例化),以及因此而導致一系列限制與困擾。

所以,我慢慢開始期待有一個更好的狀態管理庫出現。我希望它基于Mutable結構,狀態操作高效直接,而且不應破壞狀態數據類型的原始性;同時它也支持Immutable輸出,兼顧Mutable的有利于編程和操作;然后它應該是漸進式的,可以是簡潔的,也能是強大的,不會因過多的繁瑣冗余操作以及復雜概念而破壞編程樂趣。

是的,它應該是簡潔且強大的。

因此,我試著構建一個這樣狀態管庫 -- iFlow

簡介

iFlow是動態的和可擴展的, 你可以直接使用它來添加、刪除和修改State和Action;它是Mutable結構, 支持普通function和class, 并易于面向對象編程;同時它沒有任何依賴包,且非常小(5k)。需要特別說明的是iFlow定義的Store是包括Actions和State。如果你是剛涉獵狀態庫,那么在快速閱讀文檔后就可以讓你在幾分鐘內就能開始構建你的App了,因為它是極簡單的;但如果你諳熟各種狀態庫,那么它也能讓你得心應手,或許你會驚喜的發現,iFlow有些特性能高效實現出其他狀態庫不太好實現的架構設計。

從原理上說,iFlow是基于ECMAScript 2015的Proxy & Reflect。它構建的Paths Match大致過程是:先在View組件進行引用Store的State的時候獲得Getter Paths;然后在Action被觸發的時候,將通過Proxy得到Setter Path;最后,在通過觀察者來傳遞Setter Path,并在連接器內進行快速地Getter Paths Match來控制更新View組件。

  • 流程圖
流程圖

抽象化公式來表達就是: action(store) => store = newStore

基本概念

  • Store

它包含State和Actions,是State管理應用的具體部分,它可以是普通對象的形式,也可以是class的形式。

const store = iFlow({
  add (number) {
    this.counter += number
  },
  counter: 0,
}).create()

或者是

class Counter {
  constructor () {
    this.counter = 0
  }
  add (number) {
    this.counter += number
  }
}
const store = iFlow(new Counter()).create()
  • 中間件(Middleware)

iFlow提供了好幾種不同類型的中間件用于控制不同流程下的Action運行和State改變,它能控制幾乎State和Action的一切行為。

const store = iFlow({
  add (number) {
    this.counter += number
  },
  counter: 0,
}).middleware({
  stateDidChange (...args) {
    // 狀態變化后通知中間件
  }
}).create()
  • 連接器(Connector)

iFlow配合react-iflow連接器,可以讓Store和View層連接,iflow的連接器是簡單高效的。

class Example extends Component {
  render () {
    return <div onClick={() => this.props.store.add(1)}>{this.props.store.counter}</div>
  }
}
export default flow(store)(Example)

特性

  • ??支持普通function和class - 它很簡單,同時也可設計符合各種需求狀態管理架構。
  • ??Store組合 - Store Tree可以很容易共享操作Store節點。
  • ?動態和熱插拔 - 可自由插拔State和Action。
  • ??支持異步function以及其他類型的function - 可任意組合Action或由內部其他內部Action相互組合。
  • ??強大的中間件 - 中間件可以攔截控制和處理全部的State變化和Actions運行。
  • ??Store支持immutable - Store是支持被處理成immutable的Store。

優點

  • 保持數據結構的原始性

iFlow因為利用ES6 Proxy機制,因此可以保持數據結構的完整原始性,同時支持異步函數以及其他類型函數,當然也包括普通的類和函數。

  • 無樣板代碼

iFlow能給你比較自由的使用它來實現屬于符合實際開發需求的狀態數據結構設計,而不會因為各種庫的限制來變成有過多的樣板代碼。

  • 易于面向對象

有時當我們需要解耦業務代碼,尤其是中大型的項目中,我們可能需要一些面向對象編程當設計,所以狀態庫如果能支持它當然是更好了。

  • 盡可能少的選擇器

在使用Web框架(如React)的時候,iFlow是自動匹配更新的,與之對應的連接庫react-iflow可以讓你能盡可能少一些選擇器的編寫與操作,甚至在大多數情況下,使用iFlow時,你不需要選擇器。

  • 強大的中間件

如果有必要,事實上iFlow中間件是強大且有用的,完整的中間件:stateWillInitialize / actionWillStart / stateWillChange / stateDidChange / actionDidEnd,它們能實現各種需求下的狀態管理設計; 同時它也可以實現一些基礎性中間件,例如持久化中間件等等.

  • 可組合和可伸縮的Store

iFlow提倡將Store組合成store tree,不用擔心無關的Store造成一些性能上的影響,因為它是動態匹配的,你可以放心自由的組合和拓展Store。

示例

  • 簡單計數器

我們來構建一個簡單的計數器:

const store = iFlow({
  calculate (number) {
    this.counter += number
  },
  counter: 0,
}).create()

@flow(store)
class Counter extends Component {
  render() {
    return (
        <div>
        <button onClick={() => this.props.store.calculate(-1)}>-</button>
        {this.props.store.counter}
        <button onClick={() => this.props.store.calculate(1)}>+</button>
      </div>
    );
  }
}

在線運行

  • TODO

接著我們來實現一個復雜點的TODO(帶撤銷/重做/持久化)

在線運行

尾聲

最后,iFlow希望能為開發者解決在狀態管理架構和設計上可能需要的困擾,小型項目能夠更簡單輕量化,大型項目又能夠高效地各種深度設計。


如果你對iFlow感興趣的話,非常歡迎來嘗試看看,同時也非常歡迎提交PR和issue。

目前iFlow部分文檔已提供,同時后續文檔也將繼續完善中。

如果感覺它還不錯,特別歡迎給iFlow一個star,謝謝鼓勵!!!

https://github.com/unadlib/iflow

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容