You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 13:10:32