基于QtQuick(QML)的QuickFlux架构简介

基于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架构图

架构图如下:

graph LR; Action-->Dispatcher; Dispatcher-->Store; Store-->View; linkStyle 0 stroke:#aaa,stroke-width:2px; linkStyle 1 stroke:#aaa,stroke-width:2px; linkStyle 2 stroke:#aaa,stroke-width:2px; style Dispatcher fill:#f9f,stroke:#000,stroke-width:1px style Action fill:#f9f,stroke:#000,stroke-width:1px style Store fill:#f9f,stroke:#000,stroke-width:1px style View fill:#f9f,stroke:#000,stroke-width:1px

模块说明

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来进行. 如下图所示:

graph LR; Action & View'sAciton-->Dispatcher; Dispatcher-->Store; View-->View'sAciton; Store-->View; linkStyle 0 stroke:#aaa,stroke-width:2px; linkStyle 1 stroke:#aaa,stroke-width:2px; linkStyle 2 stroke:#aaa,stroke-width:2px; linkStyle 3 stroke:#aaa,stroke-width:2px; linkStyle 4 stroke:#aaa,stroke-width:2px; style Dispatcher fill:#f9f,stroke:#000,stroke-width:1px style Action fill:#f9f,stroke:#000,stroke-width:1px style Store fill:#f9f,stroke:#000,stroke-width:1px style View fill:#f9f,stroke:#000,stroke-width:1px style View'sAciton fill:#f9f,stroke:#000,stroke-width:1px

注: 上图只是一个例子, 实际使用时, 也可以在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

  • 待续
posted @ 2021-03-01 18:19  技术不支持  阅读(1574)  评论(0编辑  收藏  举报