Verge - Neue (SwiftUI / UIKit)
⚠️ 正在进行中
最新发布的Verge => master
分支
Verge - Neue是一个单向数据流框架。
架构
源代码位于VergeNeue
目录中。
演示应用程序位于VergeNeueDemo
目录中。
演示实现是非常实验性的代码。我认为没有最佳实践。因此,这些可能会更新。
- 商店 / 受限商店
- 减少器
- 突变
- 动作
let rootStore = Store(
state: RootState(),
reducer: RootReducer()
)
struct RootState {
var count: Int = 0
var photos: [Photo.ID : Photo] = [:]
var comments: [Commenet.ID : Comment] = [:]
}
struct Photo
struct Photo: Identifiable {
let id: String
let url: URL
}
struct Comment
struct Comment: Identifiable {
let id: String
let photoID: Photo.ID
let body: String
}
使用状态
struct HomeView: View {
@ObservedObject var store: Store<RootReducer>
var body: some View {
NavigationView {
List(store.state.photos) { (photo) in
NavigationLink(destination: PhotoDetailView(photoID: photo.id)) {
Cell(photo: photo, comments: self.sessionStore.state.comments(for: photo.id))
}
}
.navigationBarTitle("Home")
}
.onAppear {
self.sessionStore.dispatch { $0.fetchPhotos() }
}
}
}
PhotoDetailView
struct PhotoDetailView: View {
let photoID: Photo.ID
@EnvironmentObject var sessionStore: SessionStateReducer.StoreType
@State private var draftCommentBody: String = ""
private var photo: Photo {
sessionStore.state.photosStorage[photoID]!
}
var body: some View {
VStack {
Text("\(photo.id)")
TextField("Enter comment here", text: $draftCommentBody)
.padding(16)
Button(action: {
guard self.draftCommentBody.isEmpty == false else { return }
self.sessionStore.dispatch {
$0.submitComment(body: self.draftCommentBody, photoID: self.photoID)
}
self.draftCommentBody = ""
}) {
Text("Submit")
}
}
}
}
我们可以根据用例选择类或结构。
商店使用Reducer作为一个实例。
这意味着Reducer可能有一些依赖项。(例如数据库、API客户端)
首先,为了实现Reducer,在对象上使用ReducerType
。
然后,ReducerType
需要一个状态类型来更新状态,具有类型安全。
class RootReducer: ReducerType {
typealias TargetState = RootState
定义变异
实际上更改Verge商店状态的唯一方法是提交一个突变。
定义一个返回Mutation
对象的函数。这表示该函数是Mutation
。
Mutation
对象是一个简单的结构体,其中包含一个闭包,它将当前状态传递以更改它。
Mutation
不会运行异步操作。
extension RootReducer: ReducerType {
func syncIncrement(adding number: Int) -> Mutation {
return .init {
$0.count += number
}
}
}
提交突变
store.commit { $0.syncIncrement() }
定义动作
Action
类似于Mutation
。
Action
可以包含任意异步操作。
要将在Action内部提交突变,请使用context.commit
。
extension RootReducer: ReducerType {
func asyncIncrement() -> Action<Void> {
return .init { context in
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
context.commit { $0.syncIncrement() }
}
}
}
}
分发动作
store.dispatch { $0.asyncIncrement() }
更多还原器实例样本
func submitComment(body: String, photoID: Photo.ID) -> Action<Void> {
return .init { context in
let comment = Comment(photoID: photoID, body: body)
context.commit { _ in
.init {
$0.commentsStorage[comment.id] = comment
}
}
}
}
高级信息
ScopedStore
ScopedStore
是一个与 Store
解耦的 Node 对象。
它以 Store
作为父存储和可写键路径进行初始化,以获取父存储状态的片段。
它的副作用调度和提交会影响父存储。
并接收来自父存储的副作用。