angular - 使用 Angular2 应用 MVVM

标签 angular mvvm

我正在使用 angular2 开发一个 Web 应用程序。 MVVVM模式:模型 View ViewModel,在angular2中我们有:模型类,可以从服务器端提取数据的服务以及 View 和组件的模板。我想知道我们如何在 angular2 项目中正确应用 MVVM 架构?

最佳答案

在典型的 MVVM 模式中,您有模型对象(这都是伪代码):

class MyModel { 
   public int id;
   public string foo;
   public int bar;
   public date createdOn;
}

然后你有一个 View :
<div>{{myModelBar}}</div>
<div>{{myModelFoo}}</div>
<div>{{anotherModelBar}}</div>

你看到 View 和模型是如何不相关的吗? View 需要模型中的一些属性,但不是全部。 View 还需要模型中不存在的属性。这就是需要 View 模型的地方:
class MyViewModel {
   public string myModelFoo;
   public int myModelBar;
   public int anotherModelBar;
}

现在我们的 View 有了一个可以实际使用的模型。那么我们如何从Model到ViewModel再到View呢?我们需要一个 Controller :
class Controller() {
    var modelA = new MyModel();
    modelA.foo = "Foo";
    modelA.bar = 1;
    var modelB = new MyModel();
    modelB.bar = 2;

    var viewModel = new MyViewModel();
    viewModel.myModelFoo = modelA.foo;
    viewModel.myModelBar = modelA.bar;
    viewModel.anotherModelBar = modelB.bar;

    // The view function here would retrieve the view and combine it with the ViewModel
    var view = View('path_to_our_view_file', viewModel);

    return view;
}

这就是 MVMC 模式。我会插话并说 MVVM 模式本身毫无用处,因为您的模型、 View 和 View 模型没有关于 View 或如何组合 View 的任何行为。我在声称是 MVVM 的框架中看到的是,ViewModel 通常是 Controller 和 ViewModel 的混搭,或者他们认为该模式是无 Controller 的,因为没有路由。但是,我会说,在 ViewModel 作用于特定 View 的这些情况下,路由是隐含的。

很明显,Angular 并没有严格遵守这种模式。但是,大多数概念是相似的。您仍然有一个 Controller 和 View ,它们只是以组件的形式混合在一起。就 Controller 而言,Angular 2 的有趣之处在于您可以实际路由到 Controller ,并且您可以通过分配给组件的模板标签进行隐式路由。但是结果是一样的,你有某种方式调用或路由到组件,它检索一个 View 。与许多框架一样,模型层由您来创建。

那么 ViewModel 层在哪里呢?我建议,由于 View 可以访问 Component 中的所有公共(public)变量,因此 ViewModel 层是 Component 类的属性。在客户端必须向服务器发出请求并且服务器返回 View 的典型服务器客户端应用程序中,您需要在每次调用时重建状态。这要求您在每次调用时沿着 MVMC 链:Controller -> Model -> ViewModel -> View。在 Angular 的客户端应用程序中, Controller 保存 View 的状态,这就是 ViewModel 所在的位置。

所以问题就变成了,我们如何将 View 的关注点与 Model 的关注点分开。你只需要聪明地不要直接在你的 View 中使用模型。一种方法是创建一个单独的 View 模型作为一个类。
class MyComponentViewModel {
    name: string;
    list: Array<string>;
}

@Component({
    selector: 'my-component',
    template: `<div>{{model.name}}</div>
               <ul>
               <li *ngFor="let item of (model.list | async)">{{item}}</li>
               </ul>`
})
class MyComponent {
    model: MyComponentViewModel;
    private propertyA: string 

    constructor(private dataService: DataService) {
        this.model = new MyComponentViewModel();
        this.model.list = [];

        let page = dataService.getCurrentPage();
        let children = dataService.getPageChildren(page.id).subscribe(pages => {
            this.model.list = [];
            for(let page of pages) {
                this.model.list.push(page.title);
            }
        })

        this.model.name = page.title;
    }
}

这些代码都没有经过测试,希望你明白这一点。您可以只创建自己的 View 模型,而不是弄脏 Component 类的属性,您可以将 View 属性放在它们自己的类中。这种方法的优点是组件更简洁,关注点与 View 分离,因为您现在有一个可以使用的契约(Contract)(只要您坚持该模式)。缺点是它有点冗长,可能很难将某些类型转换为更适合 View 模型的更通用的类型,它可能会混淆 Angular 变化检测,因为您将所有属性都放在一个对象上(我'我不确定这个)。至于我,我可能不会使用这种模式,因为它看起来过于冗长。

关于angular - 使用 Angular2 应用 MVVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43316129/

相关文章:

angular - 无法实例化循环依赖! ApplicationRef ("[ERROR ->]") : in NgModule AppModule in ./AppModule@-1:-1

angular - 在 angular 6 项目中使用 jquery 库好吗?

angular - 在子文件夹下部署 Angular SPA

具有枚举值的 Angular 5 选择和默认值

javascript - 如何重构 API 调用的 if else 语句?

wcf - 通过带有私有(private)字段的 wcf 服务发送对象的问题

wpf - 我应该为我的 View 使用 UserControls 而不是 DataTemplates 吗?

c# - 具有相同 ViewModel 的多个实例的 MVVM-Light Messenger

c# - 属性调用方法或启动事件是 "wrong"

c# - 代码契约和 MVVM