数据驱动与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;

3. 包含了修改方法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。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值