基於QtQuick(QML)的QuickFlux架構簡介
簡介
QuickFlux架構是一個QtQuick架構, 是Facebook Flux架構的QML實現. 它可以有效的幫你前后端解耦, 流式處理前端數據變化及界面交互等, 使代碼結構更清晰. 隨着項目的擴大, 你的前端數據, 可能散落在各個小的QML文件中且數據和數據, 數據和界面之間的關系會變得混沌, 而該架構可以有效的解決這個問題, 它將前端數據有效的管理起來了.
名詞翻譯及簡單介紹
- Action -- 動作. 來自用戶的操作或網絡等后台引起的操作
- Dispatcher -- 調度器/調度員. 它是一個單例的消息調度器, 負責為QML引擎管理消息隊列. 因此該架構可以避免無序的消息處理, 它保證消息按順序(先到先得)到達各Store.
- Store -- 存儲. 存儲界面(view)會用到的數據, view一般只允許讀Store中的數據, 而不允許直接寫入Store, View必須要通過Dispatcher調用Action來更新Store中的數據.
- View -- 界面.
- AppDispatcher -- (應用程序)調度器/調度員.
- Middleware -- 中間件. 可以使用Middleware在數據分派到存儲(Store)組件之前插入一些操作(例如: 在數據修改時, 彈出一個確認界面.).
- Hydration -- 水合. 從JSON序列化或反序列化Store組件
- QuickFlux框架可以以源碼, 庫等方式加載到Qt項目中, 本文示例以源碼方式.
本文介紹的內容主要與Dispatcher相關, Middleware和Hydration請自行了解.
架構簡介
Flux避開了MVC,支持單向數據流. Flux中不存在控制器. 當用戶與視圖(View)區域交互時,視圖(View)通過一個中央調度程序(Dispatcher)將操作傳播到保存應用程序數據和業務邏輯的各個存儲區(Store),這些存儲區(Store)更新所有受影響的視圖(View)。
QuickFlux架構圖
架構圖如下:
模塊說明
Actions
dispatcher的公共方法, 該方法允許我們添加對Store進行分派的操作. 該方法將動作發送給dispatcher。例如,如果你需要一個delete操作, 可以在該方法中添加一個deleteSomething(), 代碼如下:
AppActions.qml
pragma Singleton
import QtQuick 2.0
import QuickFlux 1.1
import "./"
ActionCreator {
signal deleteSomething()
}
- 為了使用方便, 可以為他添加一個tab熱鍵, 這樣可以在寫代碼時自動補齊
ActionTypes.qml
pragma Singleton
import QtQuick 2.0
import QuickFlux 1.0
KeyTable {
property string startApp
property string deleteSomething
}
Dispatcher
dispatcher是管理Flux應用程序中所有數據流的中心樞紐. 它本質上是Store回調的注冊表, 本身不做過濾, 它只是一種將操作分發到Store的簡單機制. 每個Store都注冊自己並提供一個回調. 當使用者向dispatcher提供一個新Action操作時,應用程序中的所有Store都通過注冊中心中的回調接收該操作. Action操作的過濾和處理在Store中進行, 與Dispatcher無關.
Stores
Store包含應用程序狀態和邏輯, 例如后端數據是1代表男, 那么你可以在Store里存儲對應的字符串"男". 它們的作用與傳統MVC中的模型有些類似, 但是它們管理的數據或狀態, 可以被多個View使用.
Flux和MVC/MVVM設計模式之間的主要區別是"查詢"和"更新"的分離. 盡管View組件從Store讀取數據來顯示, 但它不會直接向Store中寫入數據. 對View來說, Store是一個只讀數據模型, 僅支持"查詢", 如果要"更新"Store中的數據, 它必須通過Action來進行. 如下圖所示:
注: 上圖只是一個例子, 實際使用時, 也可以在Store中根據實際情況, 觸發另一個Action.
應用框架
目錄結構:
/constants/Constants.qml
/actions/ActionTypes.qml
/actions/AppActions.qml
/views/
/stores/
/adapters/
/main.qml
actions/ActionTypes.qml
ActionTypes是一個常量表(單例組件), 用於存儲應用程序中所有可用的動作類型. 不建議通過sender和事件組合在一起來命名要做的事情(如: removeItemButtonClicked), 建議直接告訴用戶做什么(如: openItem), 如果需要, 你可以在其名稱中添加范圍前綴來限定動作的范圍(如: itemRemove)
action/AppActions.qml
AppActions是一個動作(Action)創建者, 用於通過調度員(AppDispatcher)創建和分配動作(Action), 它不知道數據模型(DataModel)也不知道誰使用數據模型, 它只依賴調度員(AppDispatcher), 所以可以在任何地方用它.
Button {
onClicked: {
AppActions.deleteSomething();
}
}
注: ActionTypes和AppActions中的內容, 已包含了應用程序的所有操作, 其他開發者打開這兩個文件就可以了解了整個API
stores
存儲(stores)可以保存應用程序的數據, 狀態和邏輯. 類似於MVVM中視圖模型. 由於Flux是單向數據流, 它對視圖是只讀的, 數據更新只能通過動作(action)來完成.
- /stores/MainStore.qml
MainStore是一個單例, 用來管理存儲.
pragma Singleton
import QtQuick 2.0
import QuickFlux 1.1
RootStore {
/// Set the source of actions from AppDispatcher
bindSource: AppDispatcher
}
- /stores/RootStore.qml
單例對象雖好, 但不利於測試, 因此引入了RootStore.qml. 為了便於測試, 不建議修改MainStore.qml來實現屬性字段, 它應該在其基類RootStore.qml中實現.
/views
- 視圖組件的文件夾, 不建議將應用程序邏輯放在視圖組件中. 因為用於處理用戶事件的代碼可能難以追蹤和測試, 他們沒有集中在一個源文件中, 依賴關系不明顯, 會造成代碼不易維護和復用.
- 在做可交互的界面時, 應該遵循只告知Action創建者: 界面想要做的操作; 而不應該直接去和Store交互(Store對View是只讀的).
/middlewares
- 待續