在 SwiftUI 中,我试图在父 ViewModel 和子 ViewModel 之间创建一些绑定,这是我的场景的简化示例:
父组件:
class ParentViewModel : ObservableObject {
@Published var name = "John Doe"
func updateName() {
self.name = "Jonnie Deer"
}
}
struct ParentView: View {
@StateObject var viewModel = ParentViewModel()
var body: some View {
VStack {
Text(viewModel.name)
ChildView(name: $viewModel.name)
// tapping the button the text on parent view is updated but not in child view
Button("Update", action: viewModel.updateName)
}
}
}
Run Code Online (Sandbox Code Playgroud)
子组件:
class ChildViewModel : ObservableObject {
var name: Binding<String>
var displayName: String {
get {
return "Hello " + name.wrappedValue
}
}
init(name: Binding<String>) {
self.name = name
}
}
struct ChildView: View {
@StateObject var viewModel: ChildViewModel
var body: some View {
Text(viewModel.displayName)
}
init(name: Binding<String>) {
_viewModel = StateObject(wrappedValue: ChildViewModel(name: name))
}
}
Run Code Online (Sandbox Code Playgroud)
因此,正如评论中所述,当我点击父组件上的按钮时,ChildView 中的名称不会更新,就好像绑定丢失一样......还有其他方法可以使用更新后的值更新视图模型吗?像getDerivedStateFromProps
在 React 中那样说(因为点击按钮时,ChildView::init
会使用新名称调用该方法。
谢谢。
Apple 非常重视单一事实来源 (SSoT) 的概念,牢记这一点可以防止您陷入这样的代码困境。您遇到的问题是,当您使用 aBinding
实例化子视图时,您正在转身并将其用作@StateObject
. @StateObject
当您这样做时,您将断开应位于 SSoT 层次结构顶部的连接。它指定您的 SSoT。否则,您有两个 SSoT,因此只能更新一个。中的视图模型ChildView
应该是一个@ObservedObject
,以便它连接到层次结构。另外,您可以ChildViewModel
在调用时直接实例化ChildView
. 初始化器只是用来解耦事物。您的观点将如下所示:
struct ParentView: View {
@StateObject var viewModel = ParentViewModel()
var body: some View {
VStack {
Text(viewModel.name)
// You can directly use the ChildViewModel to instantiate the ChildView
ChildView(viewModel: ChildViewModel(name: $viewModel.name))
Button("Update", action: viewModel.updateName)
}
}
}
struct ChildView: View {
// Make this an @ObservedObject not a @StateObject
@ObservedObject var viewModel: ChildViewModel
var body: some View {
Text(viewModel.displayName)
}
}
Run Code Online (Sandbox Code Playgroud)
两个视图模型都没有改变。
归档时间: |
|
查看次数: |
3082 次 |
最近记录: |