我正在使用 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/