对vue MVVM的探究

对vue MVVM的探究

这个问题是我在写blazor时想到的

MVVM

咱们都知道MVVM分了ModelViewModelView三层

  • Model层是数据
  • ViewModel层是给View层提供显示的数据和逻辑操作
  • View层是界面显示

在WPF里面是处理的很好,在XAML中DataContext是ViewModel,View可以直接绑定ViewModel的数据和事件,而View的界面样式和动画可以通过触发器TriggerDataTriggerEventTrigger操作,这样很容易就把三层给分开了

还有prism框架的依赖注入RegionModuleDialogNavigationEventAggregator等一系列东西

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要实现监听也有多种方式,set或者事件,抛出异常就完事了,至于说js的异常处理,反正我看不懂

还有就是官方说的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就是一坨

posted @ 2024-02-21 14:48  .NET好耶  阅读(8)  评论(0编辑  收藏  举报