- 從最開始學習
React
就接觸到Flux
架構,接著前端組件化框架都涉及到Flux
概念,例如Vue.js
中的Vuex
。一直以來Flux
都不是很好理解,但俗話說實踐出真知,只有在真正的項目場景上使用過了,才知道一個架構概念為什么要如此設計,可以帶來什么樣的好處。
Flux定義
-
Flux
是一種架構思想,用來解決軟件結構問題。 -
Flux
將一個應用分成四個部分:
View: 視圖層
Action(動作):視圖層發出的消息(比如mouseClick)
Dispatcher(派發器):用來接收Actions、執行回調函數
Store(數據層):用來存放應用的狀態,一旦發生變動,就提醒Views要更新頁面
用一張流程圖來表示:
Flux流程圖
- 在
Flux
中,數據是單向流動的:
- 用戶訪問 View
- View 發出用戶的 Action
- Dispatcher 收到 Action,要求 Store 進行相應的更新
- Store 更新后,發出一個"change"事件
- View 收到"change"事件后,更新頁面
一個實踐和理解
- 上面的定義在網上一搜就有。但相信很多人一開始和我一樣,定義看的懂,但并不理解為什么要這么做,這樣做可以帶來什么好處?接下來試著用一個在實際項目中的場景來說明一下。
業務場景
公司管理功能界面
- 界面有兩個大區域組成:
- 頂部
Header
:顯示當前操作的公司名稱- 下部
Workplace
:主要功能工作區,包含一個Tab
組件。
-
Workplace
中第一個Tab
是公司選擇功能:填寫公司名稱,點擊確定之后輸入的公司名稱成為全局變量,并且顯示在Header
中。 - 在其他Tab頁面中可以獲取到當前設定的公司名稱值。
結構設計
- 使用現在也非常流行的
Vue.js
+Vuex
來解決這個問題。 - 有一些前端模塊化框架經驗的同學應該很容易想到:
- 把兩個主區域(
Header
,Workplace
)分成兩個模塊(兩個.vue
文件)。Tab
中的N個功能頁面也對應著N個模塊(N個.vue
文件)。- 使用
route
實現點擊Tab
頁在Workplace
中切換不同的功能模塊。
-
實現的結構大致如下:
- 那么現在的問題就是如何將在
CompanySelect.vue
中設置的公司名稱,傳給Header.vue
來展示。 - 按前端模塊化的思路,每個模塊(
.vue
或.jsx
)都有自己獨立的state
與props
來處理數據與界面渲染的綁定。 - 在這個功能場景下,可以通過
App.vue
在創建Header.vue
和CompanySelect.vue
模塊的時候,設定回調函數,在CompanySelect.vue
輸入公司名稱后,由回調函數把值最終傳給Header.vue
來顯示:
Flux化
- 按
Flux
的思路來重構:
- 一個項目(或者大模塊)將會確定一個根。
- 在這個根上擁有
state
和改變state
的事件方法。- 根之下的功能模塊“舍棄”自己的
state
,數據的來源與變化改為根的state。- 功能模塊中的操作事件只會觸發根上的事件方法,不實現具體的業務邏輯。
Flux化的結構
- 在這個例子中,
CompanySelect.vue
本身將不會保存公司名稱的變量,“確定”按鈕只把輸入的值通過事件傳給根(App.vue
),由根進行保存和傳遞給其他組件。
- 失去
state
和業務邏輯的功能模塊,將會弱化成單純的顯示組件,所有的數據供給和業務邏輯由根來組裝提供。 - 這種改變,有利于復雜項目的前端模塊化,實現顯示組件的復用化。