Minimalist
不用 Rx
构建 data-driven UI
那是什么?
我是反应式框架的大粉丝。我使用过RxSwift、ReactiveSwift、Combine,每次加入不能采用其中一种框架的项目时我都很苦恼。
- 问题 #1:团队要小心复杂性以及陡峭的学习曲线
- 问题 #2:传统框架对于小型项目来说过于庞大
这个库就是从去除所有非必要部分的视角出发的。事实上,你只需用可观察属性和事件广播器构建数据驱动的UI即可。而这些就是在这个微型框架(仅100行代码)中你所能得到的一切。
@Property
也称为
BehaviorRelay
在 RxSwift 中MutableProperty
在 ReactiveSwift 中CurrentValueSubject
在 Combine 中
class ViewModel {
@Property var items: [Items]
}
// Access the current value:
viewModel.items.count
// Subscribe on changes of the value:
viewModel.$items.observe(with: self) { (obj, items) in
...
}
@Signal
也称为
PublishRelay
在 RxSwift 中Signal
在 ReactiveSwift 中PassthroughSubject
在 Combine 中
class ViewModel {
@Signal var didReceiveMessage: Accepts<Message>
}
// Broadcast a notification:
didReceiveMessage.send(message)
// Subscribe on updates:
viewModel.$didReceiveMessage.observe(with: self) { (obj, message) in
...
}
功能
访问控制
您可以使用Swift的访问控制来仅从模块外部限制对写访问。
class ViewModel {
@Property private(set) var value: String = ""
@Signal private(set) var signal: Accepts<Void>
}
// Cannot change property or trigger a signal:
viewModel.value = "abc" // ❌
viewModel.signal.send(()) // ❌
自动内存管理
订阅绑定到所提供对象的生存期,并将自动解除绑定。在回调中也会提供该对象及其值,因此您无需始终进行 [weak self]
的操作
class ViewController: UIViewController {
var tableView: UITableView
func viewDidLoad() {
...
viewModel.$items.observe(with: self) { (vc, items) in
vc.tableView.reloadData()
}
}
}
筛选状态更新(Redux)
数据驱动的UI最适合用于单向数据流设计,这可能会涉及在应用程序中使用集中式状态。
订阅后,您可以指定状态容器内值的KeyPath
以接收范围和过滤更新(就像使用distinctUntilChanged
一样)
$appState.observe(\.screens.loginScreen, with: self) { (obj, state) in
...
}