数据驱动与MVC

SiYangSimpleMvc

一个轻量级、最简、易用的Mvc框架。

https://github.com/SYRollingStone/SiYangSimpleMvc

零、MVC最简总结

一句话版:

Model 管数据,View 管显示,Controller 管交互与流程。

精确定义:

  • Model(模型)

    负责业务规则与数据状态,不关心界面如何显示。

  • View(视图)

    负责把 Model 的数据展示出来,不包含业务逻辑。

  • Controller(控制器)

    接收用户输入,协调 Model 更新,并选择/驱动 View 刷新。

一、非MVC写法

1.1 例子

一个修改金币的例子

复制代码
public class NotMvcDemo
{
    private int coin = 0;
    private TextMeshProUGUI coinText;
    private void AddCoin(int addCount)
    {
        coin+=addCount;
        coinText.text = $"{addCount}";
    }
}

这个管理类里同时包含了:

1.状态(或数据),以下都称为状态,即金币数量coin;

2.包含了显示UI coinText;

  1. 包含了修改方法AddCoin,更改了状态变化和显示变化;

状态、UI、控制方法耦合在一个文件里。

1.2 可优化地方

我们要让状态变化显示变化修改方法三者分离。

状态变化 成为驱动整个流程的核心,而不是用修改方法命令一样的改变状态和显示。

二、MVC改造

2.1 先将最简单的View独立

复制代码
[Serializable]
public class MvcDemoView
{
复制代码
  public TextMeshProUGUI coinText;

  public Button addCoinBtn;
  // 调用方法修改view
  public void RenderCoinText(int currentCoint)
  {
    if (coinText!= null)
    {
        coinText.text = $"{currentCoint}";
    }
  }
}

2.2 状态

Serializable

public class MvcDemoData

{

// SYMvcObservable是封装的数据变化通知,看2.3说明,当对值set就发通知

复制代码
public SYMvcObservable<int> coin = new();

public void AddCoint(int addCoinCount)
{
    coin.Value  += addCoinCount;
}

}

2.3 数据变化通知

我们的目的是状态中的数据变化了,View就要随之更改,所以封装一个类做到这一点:

复制代码
public sealed  class SYMvcObservable<T>
{
    private T _value;        // 数据
    public event Action<T> Changed;        // 数据变化set,就执行Action

    public SYMvcObservable(T initial = default) => _value = initial;

    public T Value
    {
        get => _value;
        set
        {
            if (Equals(_value, value)) return;
            _value = value;
            Changed?.Invoke(_value);
        }
    }
}

我们用SYMvcObservable对一条数据做一个封装,当数据set改变的时候,就执行Changed。

2.4 让Changed和修改View绑定

复制代码
public static  class BindUtil
{
    /// <summary>
    /// 订阅 Observable 变化并立即渲染一次;自动把解绑动作登记到 disposer。
    /// </summary>
    public static void Bind<T>(this SYMvcDisposer disposer, SYMvcObservable<T> obs, Action<T> render, bool renderImmediately = true)
    {
        if (obs == null || render == null) return;

        obs.Changed += render;
        disposer.Add(() => obs.Changed -= render);

        if (renderImmediately)
            render(obs.Value);
    }

}

2.5 SYMvcDisposer类存储data和view的绑定,并且在合适的时机释放

复制代码
// 缓存起来,在合适的时候统一释放
public  sealed  class SYMvcDisposer : IDisposable
{
    private readonly List<Action> _undos = new();

    public void Add(Action undo)
    {
        if (undo != null) _undos.Add(undo);
    }

    public void Dispose()
    {
        for (int i = _undos.Count - 1; i >= 0; i--)
            _undos[i]?.Invoke();
        _undos.Clear();
    }
}

2.6 在Controller中创建data和view的绑定,和释放。

复制代码
using System.Collections;
using System.Collections.Generic;
using SiYangMVC.Runtime;
using UnityEngine;

public class AddCointController : MonoBehaviour,IMvcController
{
    private AddCoinModel _data = new();

    [SerializeField] private AddCoinView _view;
    // 暂时存储绑定关系,方便在某个时刻释放。
    private SYMvcDisposer _disposer;
    
    private void OnEnable()
    {
        Bind();
    }

    private void OnDisable()
    {
        Unbind();
    }

    public void Bind()
    {
        _disposer = new SYMvcDisposer();
        
        _disposer.Bind(_data.coin , _view.RenderCoinText);
        
        // 对Button的绑定
        _disposer.OnClick(_view.addCoinBtn,()=>SetTouchTipVisible(5));
    }

    public void Unbind()
    {
        _disposer?.Dispose();
        _disposer = null;
    }
    
    //----------api-------------
    public void SetTouchTipVisible(int addCoint)
    {
        _data.AddCoint(addCoint);
    }
}

MVC的C指Controller,在Controller中更新model,再更新view。

我们实现了一个数据绑定,更新model后,model会利用绑定的Action更新View。

相关推荐
DaLiangChen4 小时前
Unity 实用工具:动态绘制物体边界包围盒(支持屏幕固定线宽)
unity·游戏引擎
张老师带你学4 小时前
Unity 食物 农产品相关
科技·游戏·unity·游戏引擎·模型
mxwin4 小时前
Unity Custom Interpolators与半透明阴影的原理与实战
unity·游戏引擎·shader
晴夏。5 小时前
UE5第三人称模板实现及相关引擎源码分析
unity·ue5·游戏引擎·ue
budingxiaomoli9 小时前
Spring Web MVC 知识总结
spring·mvc
天人合一peng10 小时前
Unity工程发布hololens需安装, MRTK安装
unity·游戏引擎·hololens
魔士于安11 小时前
Unity类似博物馆场景
前端·unity·游戏引擎·贴图·模型
小拉达不是臭老鼠11 小时前
Unity数据持久化_XML
学习·unity
RReality12 小时前
【Unity Shader URP】模板遮罩 / 传送门 实战教程
ui·unity·游戏引擎·图形渲染·材质
zdr尽职尽责1 天前
Untiy 处理Aseprite 资产 解决偏移问题
学习·unity·c#·游戏引擎