如何使用@Observable宏将父ViewModel的属性绑定到子ViewModel的属性
如何使用@Observable宏将父ViewModel的属性绑定到子ViewModel的属性
嘿,我太懂你那种在View里硬塞@Binding当中间人的憋屈了——明明就是想让父子ViewModel的属性直接打通,何必让View来当这个多余的传声筒呢?用@Observable宏其实有两种超清爽的直接做法,我给你一步步讲清楚:
方法一:让子VM直接持有父VM的引用,代理属性
这种方法适合父子ViewModel关系比较紧密的场景,子VM直接拿到父VM的实例,通过代理属性来读写父VM的age,因为@Observable的属性本身是可观察的,只要父VM的age变化,关联的View会自动刷新。
先看父ViewModel的代码:
@Observable class ProfileViewModel { var age = 25 // 我们要绑定的目标属性 }
然后是子ViewModel:
class AgePickerViewModel { private let profileVM: ProfileViewModel // 子VM的age属性直接代理父VM的age,读写都直接作用在父VM上 var age: Int { get { profileVM.age } set { profileVM.age = newValue } } // 初始化的时候传入父VM实例 init(profileVM: ProfileViewModel) { self.profileVM = profileVM } }
最后是View层的用法,完全不用管绑定逻辑:
struct ProfileView: View { @State private var profileVM = ProfileViewModel() var body: some View { // 直接把父VM传给子VM初始化 let agePickerVM = AgePickerViewModel(profileVM: profileVM) AgePickerView(viewModel: agePickerVM) } } struct AgePickerView: View { let viewModel: AgePickerViewModel var body: some View { // 直接用子VM的age属性就行,自动和父VM联动 Stepper("年龄: \(viewModel.age)", value: $viewModel.age) } }
这种方式把属性联动的逻辑完全放在VM层,View只需要负责展示,是不是比之前在View里绕来绕去舒服多了?
方法二:给子VM传递属性的绑定,保持子VM独立性
如果你想让子ViewModel更独立,不想让它知道父VM的存在(比如以后想把这个子VM复用给其他父VM),可以直接给子VM传入父VM属性的绑定对象。
父ViewModel还是一样:
@Observable class ProfileViewModel { var age = 25 }
子ViewModel改成持有绑定对象:
class AgePickerViewModel { let age: Binding<Int> // 初始化的时候直接传入age的绑定 init(age: Binding<Int>) { self.age = age } }
View层的用法也很简单:
struct ProfileView: View { @State private var profileVM = ProfileViewModel() var body: some View { // 把父VM的age绑定传给子VM let agePickerVM = AgePickerViewModel(age: $profileVM.age) AgePickerView(viewModel: agePickerVM) } } struct AgePickerView: View { let viewModel: AgePickerViewModel var body: some View { // 用子VM的age绑定,通过wrappedValue拿到当前值 Stepper("年龄: \(viewModel.age.wrappedValue)", value: viewModel.age) } }
这种方式下子VM完全不用关心父VM是什么,只需要处理拿到的age绑定,复用性拉满,适合需要通用子VM的场景。
内容来源于stack exchange
相关产品推荐
相关产品推荐

