VergeNeue 6.0.0-alpha.1

VergeNeue 6.0.0-alpha.1

muukii维护。



VergeNeue 6.0.0-alpha.1

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 作为父存储和可写键路径进行初始化,以获取父存储状态的片段。

它的副作用调度和提交会影响父存储。
并接收来自父存储的副作用。