对vue MVVM的探究
这个问题是我在写blazor时想到的
MVVM
咱们都知道MVVM分了Model
、ViewModel
、View
三层
- Model层是数据
- ViewModel层是给View层提供显示的数据和逻辑操作
- View层是界面显示
在WPF里面是处理的很好,在XAML中DataContext
是ViewModel,View可以直接绑定ViewModel的数据和事件,而View的界面样式和动画可以通过触发器Trigger
、DataTrigger
、EventTrigger
操作,这样很容易就把三层给分开了
还有prism框架的依赖注入
、Region
、Module
、Dialog
、Navigation
、EventAggregator
等一系列东西
blazor MVVM
到了blazor里面再用MVVM很容易就发现问题了,因为是基于.net的,所以依赖注入这种基本的东西还是有的,要实现DataContext也不是难事,View层通过DataContext.
的方式绑定数据和事件,但是这玩意儿的View毕竟是html,没有触发器和事件状态呀
没有触发器和事件状态意味着不能在标签语句中处理动画,不过这里可以通过View层代码操作动画和调用ViewModel事件,也算是符合MVVM
不过没有触发器还有个问题,那就是异步,如果要保证异步事件中数据不会被上一个异步事件操作,那就要把上一个异步事件中断掉,WPF里面也是要做这个处理的,但是因为WPF有触发器,所以不需要处理中断后的数据,比如动画状态之类的
vue MVVM
到这里问题就更多了,毕竟官方也没说完全遵守MVVM的规范
首先就是没有依赖注入,虽然官方说有依赖注入,但是说实话,我是不觉得vue那玩意儿算依赖注入,且不说js里面用key和value的方式注入,毕竟.net底层估计也差不多,用ts也可以通过类型注入,为什么我觉得不算依赖注入呢,因为js还有个对象拷贝的问题
根据vue的官方文档对依赖注入的描述
当提供/注入响应式的数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中。这样可以确保所提供状态的声明和变更操作都内聚在同一个组件内,使其更容易维护。
但是这句话的意思应该就是说这玩意儿就是个大号的有读写权限的props,那么我们的ViewModel就需要手动创建,而且还需要reactive
小小的测试一波,官方文档说的是响应式状态,那我就测一个不用reactive和ref的例子
provide("a", { a: 1 });
let a1 = inject("a");
console.log(a1);
a1.a = a1.a + 1;
let a2 = inject("a");
console.log(a2);
还真是单例的
因为vue的View也是html,所以不可避免的,同样没有触发器和事件状态,那么View层也需要通过View层代码操作动画和调用ViewModel事件
至于异步事件,我觉得js的异步比.net的处理还是麻烦的多,Promise的中断没有Task方便,不过异步事件的处理还是差不多的
中断Task是比较简单,一个事件函数底下的async函数链传递同一个的CancellationToken
//在事件执行前中断上一个事件
if (null != cancellationTokenSource)
{
cancellationTokenSource.Cancel();
}
cancellationTokenSource = new CancellationTokenSource();
//执行具体的事件函数
...
具体的异步耗时操作要手动判断是否中断,抛出OperationCanceledException异常
if (true == cancellationTokenSource.Token.IsCancellationRequested)
{
cancellationTokenSource.Token.ThrowIfCancellationRequested();
}
其实也可以去掉这个判断直接调用ThrowIfCancellationRequested,因为这个函数就是这样
public void ThrowIfCancellationRequested()
{
if (IsCancellationRequested)
ThrowOperationCanceledException();
}
不过一般来说都不需要我们手动写这个,除非这个函数没有对应的CancellationToken重载
中断Promise就比较麻烦了,需要封装一个Promise,监听abort事件,中断之后再解除事件监听
FooAsync(foo: () => {}, abort: AbortController): Promise<void>
{
if (true == abort?.signal.aborted)
{
return Promise.reject();
}
return new Promise((resolve, reject) =>
{
let abortHandler = () =>
{
abort?.signal?.removeEventListener("abort", abortHandler);
reject();
};
abort?.signal?.addEventListener("abort", abortHandler);
//函数执行
foo();
//函数完成
resolve();
abort?.signal?.removeEventListener("abort", abortHandler);
});
}
大概是这样的,我没测试过,随手写的
js这里可以通过事件监听中断异步,.net则需要手动,不过.net的类库基本都封装好了,js则没有,.net要实现监听也有多种方式
还有就是官方说的MVVM,似乎指的是
Model
let data = reactive({
});
ViewModel
let methods = reactive({
});
View
<template>
</template>
而没有完全遵守MVVM的规范指的是
proxy.$refs
emmm,这算MVVM吗,我不好说
对vue MVVM的探究 结束
只能手动保持MVVM的规范,不过在vue里搞MVVM似乎没啥意义,我还没见过哪个vue项目有规范的MVVM呢,毕竟js就是一坨
标签:异步,vue,MVVM,探究,abort,事件,View From: https://www.cnblogs.com/zzy-tongzhi-cnblog/p/18022632