mvc示意图
- 用户通过试图进行输入,通知Control进行处理
- Control要求Model改变状态
- Control也可以要求View改变显示
- View一般向Model注册事件,Model改变,会通知view做出相应改变
- View也会持有model的引用,也可以直接访问model的某些数据
public class Model
{
private bool a;
public bool A
{
get => a;
set
{
a = value;
//4.model通知view
temp?.Invoke(a);
}
}
public event Action<bool> temp;
public void Add(Action<bool> a)
{
temp += a;
}
}
public class Control
{
//省略初始化
private Model model;
private View view;
public Control(Model model)
{
this.model = model;
this.view = new View(model,this);
}
public void SetA(bool a)
{
//2.改变model状态
model.A = a;
//3.改变view显示
view.SetActive();
}
}
public class View
{
private Model model;
private Control control;
public Text text;
public Toggle toggle;
public View(Model model,Control control)
{
this.model = model;
this.control = control;
model.Add(function);
//1.用户输入
toggle.onValueChanged.AddListener(control.SetA);
}
public void function(bool a) {
toggle.isOn = a;
}
public void SetActive()
{
//5.获取数据
bool active = model.A;
text.gameObject.SetActive(active);
}
}
MVVM示意图
- view :ui界面,显示数据并与用户交互
- model:实体数据,包括本地和远程
- viewmodel:负责完成View于Model间的交互,负责业务逻辑
双向绑定和单向绑定
- 单项绑定:view变化不通知viewmodel,viewmodel变化会反映在view上,例如text
- 双向绑定:view和viewmodel变化后,都互相通知对方,例如toggle
单项绑定原理
双向绑定原理
无限滑动列表原理
UI整体结构
案例
-- view
local function OnCreate(self)
self:Bind("my_tog","toggle")
self:Bind("my_btn.visible","toggle")
end
-- viewmodel
function UILoginViewModel:OnCreate()
self.toggle = BindableProperty.New(true)
end
绑定背后
-
设置manifest
-
更具manifest上的名称获取unity对应component,在获取相应的lua封装component
C2LuaType = {
["UnityEngine.UI.Button"] = UIButton,
["UnityEngine.UI.InputField"] = UIInput,
["UnityEngine.UI.Slider"] = UISlider,
["UnityEngine.UI.Text"] = UIText,
["UnityEngine.UI.Image"] = UIImage,
["UnityEngine.UI.Toggle"] = UIToggle,
["UnityEngine.UI.Dropdown"] = UIDropdown,
},
- component 进行绑定
local UIButton = BaseClass("UIButton", UIBaseComponent)
local base = UIBaseComponent
local error = error
local PropertiesHelper = require "Framework.UI.Wrapper.PropertiesHelper"
-- 创建
function UIButton:OnCreate(item, binder)
base.OnCreate(self)
self._origin = item
-- Unity侧原生组件
self.unity_uibutton = item
self.binder = binder
assert(not IsNull(self.unity_uibutton), "Err : unity_uibutton nil!")
end
--- property bind
local _interactable = "interactable"
function UIButton:interactable(property_name)
if self:IsBinded(_interactable) then
error(("UIButton %s has bind"):format(_interactable))
return
end
self.binder:Add(property_name, function (oldValue, newValue)
if oldValue ~= newValue then
self.unity_uibutton.interactable = newValue
end
end)
self:RecordProperty(_interactable)
end
local _onClick = "onClick"
function UIButton:onClick(property_name)
if self:IsBinded(_onClick) then
error(("UIButton %s has bind"):format(_onClick))
return
end
self.binder:RegisterEvent(function(viewModel, property)
self.unity_uibutton.onClick:AddListener(property)
end,nil, property_name)
self:RecordProperty(_onClick)
end
-- 资源释放
function UIButton:OnDestroy()
self.unity_uibutton.onClick:RemoveAllListeners()
self.unity_uibutton = nil
self.__onclick = nil
base.OnDestroy(self)
end
return PropertiesHelper:Extends(UIButton)
UI层级
- 二者都是值越小越先渲染
lua 面向对象
-- 简介
local UIItemsProxy = {
__index = function(t,k)
error(("items.%s not exist."):format(k))
end,
__newindex = function(t,k,v)
error(("UIItemsProxy is readonly. attempt to modifying '%s' was ignored."):format(k))
end
}
function UIItemsProxy:New(manifest)
local o = {}
setmetatable(o, self)
return o
end
return UIItemsProxy
- middleclass juejin.cn/post/684490…
local class = require("framework.lib.middleclass")
local super = require("framework.lib.super")
local ActorRunner = class("ActorRunner",super)
function ActorRunner:initialize(caster, actor_id)
end
return ActorRunner
--使用
local a = ActorRunner:new(...)