目录
- [MVVM 中 View 与 ViewModel 核心关系报告](#MVVM 中 View 与 ViewModel 核心关系报告)
-
- [一、宏观说明:V 与 VM 的三大核心关系](#一、宏观说明:V 与 VM 的三大核心关系)
- [二、分关系代码示例 + 通俗理解](#二、分关系代码示例 + 通俗理解)
-
- [1. 关系一:V 主动调用 VM(核心依赖)](#1. 关系一:V 主动调用 VM(核心依赖))
- [2. 关系二:VM 广播通知 V(反向通信)](#2. 关系二:VM 广播通知 V(反向通信))
- [3. 关系三:V ↔ VM 双向绑定(属性同步)](#3. 关系三:V ↔ VM 双向绑定(属性同步))
- 三、宏观总结
- 四、为什么必须这样梳理、理解?
- [MVVM ViewModel 内部 V/M 分层精简核心报告](#MVVM ViewModel 内部 V/M 分层精简核心报告)
-
- 一、核心前提
- 二、两层核心职责(精简版)
-
- [1\. VM\-V 视图适配层(对外)](#1. VM-V 视图适配层(对外))
- [2\. VM\-M 业务数据层(对内)](#2. VM-M 业务数据层(对内))
- [三、VM 内部 V/M 交互黄金规则](#三、VM 内部 V/M 交互黄金规则)
- 四、核心精简代码示例
-
- [1\. 底层数据与 VM\-M(纯业务)](#1. 底层数据与 VM-M(纯业务))
- [2\. 绑定基类(双向绑定基础)](#2. 绑定基类(双向绑定基础))
- [3\. VM\-V(核心交互层)](#3. VM-V(核心交互层))
- [4\. View 层(仅对接 VM\-V)](#4. View 层(仅对接 VM-V))
- 五、全链路极简流程
- 六、核心禁忌(重点)
- 七、梳理该架构的核心意义
- 八、最终一句话总结
MVVM 中 View 与 ViewModel 核心关系报告
一、宏观说明:V 与 VM 的三大核心关系
View(视图,页面/UI)和 ViewModel(业务逻辑/数据层)是单向依赖 + 双向通信 ,严格遵守:V 依赖 VM,VM 绝不依赖 V,核心关系只有 3 种:
- V 主动调用 VM (核心依赖)
V 持有 VM 实例,主动读取 VM 的属性 (展示数据)、调用 VM 的方法/命令(触发业务逻辑)。 - VM 广播通知 V (反向通信)
VM 不直接操作 UI,通过事件/消息广播通知,V 自己监听并执行弹窗、跳转、加载等 UI 行为。 - V ↔ VM 双向绑定 (数据同步)
框架自动封装:VM 属性变 → 自动更新 V;V 输入变 → 自动回写 VM,实现属性值同步。
二、分关系代码示例 + 通俗理解
1. 关系一:V 主动调用 VM(核心依赖)
理解 :V 是"使用者",VM 是"工具人",V 主动找 VM 拿数据、办事情。
场景:页面显示用户名、点击登录按钮。
csharp
// ========== ViewModel(只提供数据和方法,不认识 V) ==========
public class LoginVM
{
// 公开属性:V 用来读取展示
public string UserName { get; set; } = "张三";
// 公开方法:V 用来调用触发业务
public void DoLogin()
{
Console.WriteLine("执行登录逻辑...");
}
}
// ========== View(主动依赖 VM,调用属性+方法) ==========
public class LoginPage
{
// V 持有 VM 实例(唯一依赖方向)
private LoginVM _vm = new LoginVM();
public void ShowPage()
{
// 1. V 调用 VM 属性:读取数据展示
Console.WriteLine("用户名:" + _vm.UserName);
// 2. V 调用 VM 方法:触发业务
_vm.DoLogin();
}
}
2. 关系二:VM 广播通知 V(反向通信)
理解 :VM 是"电台",只发广播;V 是"收音机",自己听广播自己做事,VM 完全不调用 V 。
场景:登录成功后弹窗、页面跳转、显示加载动画。
csharp
// ========== ViewModel(只发通知,不操作 UI) ==========
public class LoginVM
{
// 定义广播事件(电台频道)
public event Action ShowSuccessPopup;
public void DoLogin()
{
Console.WriteLine("登录成功!");
// VM 广播通知:谁听谁处理,不知道 V 存在
ShowSuccessPopup?.Invoke();
}
}
// ========== View(自己监听,自己执行 UI) ==========
public class LoginPage
{
private LoginVM _vm = new LoginVM();
public LoginPage()
{
// V 主动订阅 VM 的广播
_vm.ShowSuccessPopup += () =>
{
// 所有 UI 操作,全由 V 自己执行
Console.WriteLine("【UI弹窗】登录成功!");
};
}
}
3. 关系三:V ↔ VM 双向绑定(属性同步)
理解 :框架自动帮你写好"监听代码",数据变了自动同步,不用手动赋值,只同步属性值 。
底层本质:单向调用 + 单向通知的封装语法糖。
csharp
// ========== 1. 双向绑定基础:通知属性变化 ==========
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
// ========== 2. ViewModel:支持双向绑定的属性 ==========
public class LoginVM : INotifyPropertyChanged
{
private string _userName;
public string UserName
{
get => _userName;
set
{
_userName = value;
// VM 通知:我的属性变了
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UserName)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
// ========== 3. View(框架自动实现双向同步) ==========
public class LoginPage
{
private LoginVM _vm = new LoginVM();
public LoginPage()
{
// 框架自动做两件事:
// ① VM 变 → 更新 V(监听通知)
_vm.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(_vm.UserName))
输入框.Text = _vm.UserName;
};
// ② V 变 → 写回 VM(主动调用)
输入框.TextChanged += (s, e) =>
{
_vm.UserName = 输入框.Text;
};
}
}
三、宏观总结
- 唯一依赖 :
V → VM(V 调用 VM 的属性、方法),VM 永远不依赖、不调用 V; - 反向通信:VM 只广播通知,V 自己监听执行 UI 行为;
- 双向绑定 :框架封装的数据同步工具,= V 调用 VM + VM 通知 V;
- 清晰边界:数据/展示走绑定,交互/业务走调用,UI 行为走通知。
四、为什么必须这样梳理、理解?
- 不混乱:把"调用、通知、绑定"彻底分开,再也不会混淆 MVVM 通信逻辑;
- 符合设计规范 :严格遵守
VM 无 UI 依赖,代码可测试、易维护、不耦合; - 所有框架通用:Vue/React/WPF/MAUI 全是这套逻辑,学会底层思想一通百通;
- 写出高质量代码:避免 VM 直接操作 UI(烂代码根源),分工明确、bug 更少;
- 夯实架构思维:从"会写代码"升级到"懂设计模式",是进阶程序员的核心能力。
MVVM ViewModel 内部 V/M 分层精简核心报告
一、核心前提
标准MVVM核心规则:View 单向依赖 ViewModel,ViewModel 绝不依赖 View。
为解耦 UI 与业务,可将 ViewModel 内部分为两层:
-
VM-V(视图适配层):对外对接 View,负责所有 UI 交互
-
VM-M(业务数据层):对内对接 Model,负责纯业务数据逻辑
重点:V 与 VM 的调用、通知、双向绑定,全部属于 VM-V,和 VM-M 无关。
二、两层核心职责(精简版)
1. VM-V 视图适配层(对外)
只做 UI 适配,无纯业务逻辑,包含三类核心内容:
-
双向绑定属性(UI 数据同步)
-
公开方法/命令(View 交互调用)
-
UI 通知事件(弹窗、跳转等 UI 行为通知)
2. VM-M 业务数据层(对内)
无任何 UI 依赖,可独立单元测试,负责:网络请求、数据校验、业务计算、原始数据处理,不感知、不操作 UI。
三、VM 内部 V/M 交互黄金规则
-
必须交互:VM 作为 UI 与业务的桥梁,两层必须配合完成业务流程。
-
单向依赖(铁律) :仅允许 VM-V → VM-M,禁止 VM-M 反向依赖、操作 VM-V。
-
交互归属 :所有两层交互代码全部写在 VM-V。VM-V 主动调用业务、接收数据、适配 UI、触发通知;VM-M 只负责执行业务、返回纯数据。
四、核心精简代码示例
1. 底层数据与 VM-M(纯业务)
csharp
// 数据模型
public class UserModel
{
public string Account { get; set; }
public string NickName { get; set; }
}
// VM-M:纯业务,无UI依赖
public class VmModelPart
{
public async Task<UserModel> LoginAsync(string account, string pwd)
{
await Task.Delay(100);
return new UserModel { Account = account, NickName = "登录用户" };
}
}
2. 绑定基类(双向绑定基础)
csharp
public interface INotifyPropertyChanged { event PropertyChangedEventHandler PropertyChanged; }
public class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropChanged(string propName)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
3. VM-V(核心交互层)
csharp
public class VmViewPart : BindableBase
{
// 单向依赖业务层
private readonly VmModelPart _bizPart = new VmModelPart();
// 双向绑定属性
private string _inputAccount;
public string InputAccount
{
get => _inputAccount;
set { _inputAccount = value; RaisePropChanged(nameof(InputAccount)); }
}
private string _showNickName;
public string ShowNickName
{
get => _showNickName;
set { _showNickName = value; RaisePropChanged(nameof(ShowNickName)); }
}
// UI通知事件
public event Action LoginSuccessEvent;
// 供View调用的入口方法
public async void Login()
{
// 调用业务逻辑
var res = await _bizPart.LoginAsync(InputAccount, "123456");
// 适配更新UI数据
ShowNickName = res.NickName;
// 通知View执行UI操作
LoginSuccessEvent?.Invoke();
}
}
4. View 层(仅对接 VM-V)
csharp
public class LoginView
{
private readonly VmViewPart _vm = new VmViewPart();
public LoginView()
{
// 监听通知,自主执行UI逻辑
_vm.LoginSuccessEvent += () => Console.WriteLine("View:执行弹窗/跳转");
}
// 页面交互调用VM
public void OnLoginClick() => _vm.Login();
}
五、全链路极简流程
-
View → VM-V:用户交互,调用方法、同步表单数据
-
VM-V → VM-M:触发纯业务逻辑
-
VM-M → VM-V:返回纯数据,无UI操作
-
VM-V → View:更新绑定数据、广播UI通知
六、核心禁忌(重点)
禁止 VM-M 操作/依赖 VM-V:业务层一旦触碰 UI 属性、UI 事件,会造成架构耦合、无法单元测试、维护成本剧增。
七、梳理该架构的核心意义
-
解耦清晰:UI 交互与纯业务逻辑完全隔离,互不干扰;
-
可测可维护:VM-M 无UI依赖,可独立单元测试,UI迭代不改动业务;
-
代码规范统一:UI逻辑收敛VM-V,业务逻辑收敛VM-M,结构清晰;
-
打通架构闭环:彻底理解MVVM内外层交互原理,摆脱只会用不懂底层的问题。
八、最终一句话总结
ViewModel 内部分为视图适配(VM-V)和业务数据(VM-M)两层,所有 UI 交互归属 VM-V,VM-V 单向调用 VM-M,业务层零 UI 依赖,实现 MVVM 最大解耦优势。