简体   繁体   English

我应该在不同的视图中重用视图模型吗?

[英]Should I reuse view models in different views?

I noticed that I have views that need the same information like others.我注意到我的视图需要与其他人一样的信息。 But sometimes you need 5 properties of the view model and sometimes only 2.但有时你需要视图模型的 5 个属性,有时只需要 2 个。

Do you share such view model over many views or do you create a separate view model for each view or maybe do you prefere an inheritance or composition strategy?您是在多个视图上共享这样的视图模型,还是为每个视图创建单独的视图模型,或者您是否更喜欢继承组合策略?

For me there are some disadvantages for sharing view models:对我来说,共享视图模型有一些缺点:

  1. Principle of Least Surprise: It is strange to fill only 2 properties of 5 of a view model and get null reference exception, because you don't want to query additional data of the database.最小惊喜原则:一个视图模型只填充5个的2个属性,得到空引用异常,很奇怪,因为你不想查询数据库的额外数据。 When the view model has 5 properties I expect that all are filled.当视图模型有 5 个属性时,我希望所有属性都被填充。 The exceptions prove the rule.例外证明了规则。
  2. Separation of Concerns/Single Responsibility Principle: The view model cluttered up on complex sites, because you have to suit different needs for each view.关注点分离/单一职责原则:视图模型在复杂站点上杂乱无章,因为您必须满足每个视图的不同需求。 If logic is involved its getting more complex, too.如果涉及逻辑,它也会变得更加复杂。

What do you think?你怎么认为? How do you handle such circumstances?你如何处理这样的情况?

People tend to have different philosophies of ViewModels based on their perspective of their use.人们倾向于根据他们使用的观点对 ViewModel 有不同的理念。 ViewModels are the glue between a view and a model and people will typically base their answer on which of the two ends they like to hold more rigid. ViewModels 是视图和模型之间的粘合剂,人们通常会根据他们喜欢更严格的两端中的哪一个来回答。

  • If you like your model/data objects to be more rigid, then you'll tend to tie the ViewModel closer to the model/data—ie you'll have a single ViewModel that is used in multiple views and let the ViewModel determine which properties to retrieve based on how you want to handle data loading (and defer things like images or other long-load properties, etc.).如果你喜欢你的模型/数据对象更严格,那么你会倾向于将 ViewModel 与模型/数据联系得更近——也就是说,你将有一个在多个视图中使用的 ViewModel,并让 ViewModel 确定哪些属性根据您希望如何处理数据加载进行检索(并推迟图像或其他长时间加载属性等)。
  • If you like your Views to be more rigid, then you'll tie the ViewModel closer to the View—ie have a separate ViewModel for each view and let the model/data objects handle things like syncronization as you move from view to view.如果您希望您的视图更加严格,那么您可以将 ViewModel 与 View 联系在一起,即每个视图都有一个单独的 ViewModel,并让模型/数据对象在您从一个视图移动到另一个视图时处理诸如同步之类的事情。

Personally, I prefer the first as my data tends to be more rigid because it's less likely to change than the views are (in my projects—I don't think that's a universal property of data and views).就我个人而言,我更喜欢第一个,因为我的数据往往更严格,因为它比视图更不可能改变(在我的项目中 - 我不认为这是数据和视图的普遍属性)。 Since change notifications are a natural feature of ViewModels, I don't have to make my model objects communicate changes if a user happens to have two views up that show the same/similar data.由于更改通知是 ViewModel 的一个自然功能,如果用户碰巧有两个显示相同/相似数据的视图,我不必让我的模型对象传达更改。

In the project I am working on, each view has its own ViewModel, however we also have CollectionViewModels, which are shared/referenced by multiple view models.在我正在处理的项目中,每个视图都有自己的 ViewModel,但是我们也有 CollectionViewModel,它们被多个视图模型共享/引用。

Think - a list of Suppliers, that needs to be displayed in multiple screens in your application - and is bound to a variety of controls - a list box, grid view, whatever you need.想想——一个供应商列表,需要在你的应用程序的多个屏幕中显示——并且绑定到各种控件——一个列表框、网格视图,无论你需要什么。 Having just one ViewModel makes for simpler update/refresh logic of the list of Suppliers.只有一个 ViewModel 可以简化供应商列表的更新/刷新逻辑。

TLDR: I would only reuse view models, if all usage cases use the ViewModel in the same way. TLDR:如果所有用例都以相同的方式使用 ViewModel,我只会重用视图模型。 Ie they all use the same properties etc.即它们都使用相同的属性等。

I would have a seperate ViewModel for each view.对于每个视图,我都会有一个单独的 ViewModel。 Unused properties make the code less readable (Why is that property present if it isn't being used?).未使用的属性会降低代码的可读性(如果不使用该属性,为什么会出现该属性?)。 If you have the same functionality for a fixed set of properties over several views I could see using a base class which contains those properties.如果您对多个视图上的一组固定属性具有相同的功能,我可以看到使用包含这些属性的基类。

Definitely one ViewModel per View, imho.每个视图肯定有一个 ViewModel,恕我直言。

As your application grows in complexity shared ViewModels will tend to grow, and it doesn't feel great to pass an object with 50 properties to a View when all it needs is one property.随着您的应用程序复杂性的增加,共享 ViewModel 将趋于增长,并且当它只需要一个属性时,将具有 50 个属性的对象传递给 View 感觉不太好。

Also, sometimes you may want to add extra properties in your ViewModel that are absolutely specific to your View and that you don't need in other Views.此外,有时您可能希望在您的 ViewModel 中添加额外的属性,这些属性绝对特定于您的视图,并且您在其他视图中不需要。 Say you have a CSS class that depends on properties from the ViewModel.假设您有一个依赖于 ViewModel 属性的 CSS 类。 Instead of writing if else statements in your View, you create a property in the ViewModel that returns the correct css class based on whatever business rules you have.您无需在 View 中编写 if else 语句,而是在 ViewModel 中创建一个属性,该属性根据您拥有的任何业务规则返回正确的 css 类。 This way you make the View as slim as possible and with a dedicated ViewModel you are not sharing a CSS class name with Views that don't really care about it.通过这种方式,您可以使 View 尽可能纤薄,并且使用专用的 ViewModel 您不会与并不真正关心它的 View 共享 CSS 类名。

I usually share ViewModels.我通常共享 ViewModel。 As I understand it, the advantages of using view models are (a) security, in that properties that should be hidden are and (b) separation of concerns between business and presentation layers.据我了解,使用视图模型的优点是 (a) 安全性,因为应该隐藏的属性是 (b) 业务层和表示层之间的关注点分离。 (b) is accomplished just the same while sharing view models. (b) 在共享视图模型时完成相同的操作。

As for (a), I'm rarely in a situation where exposing a property is a security risk in one place but not in another.至于(a),我很少遇到在一个地方暴露财产是安全风险而在另一个地方不存在的情况。 If a property needs to be hidden, it probably needs to be hidden everywhere.如果一个属性需要隐藏,它可能需要在任何地方隐藏。 Of course, YMMV, but this seems like a fairly subjective question.当然,YMMV,但这似乎是一个相当主观的问题。

I use Entity Framework with Code First so my domain classes need to remain pretty rigid as they will be mapped to a sql database.我将实体框架与 Code First 一起使用,因此我的域类需要保持非常严格,因为它们将被映射到 sql 数据库。

Some views use just one directly mapped entity and that's just great so I use the same domain layer entity.有些视图只使用一个直接映射的实体,这很好,所以我使用相同的域层实体。 If that entity requires more information (two password fields for example) I will use composition.如果该实体需要更多信息(例如两个密码字段),我将使用组合。 'Composition should be favoured over inheritance', so if you can use composition do so, usually as it's just additional properties, composition can be used. '组合应该优先于继承',所以如果你可以使用组合,通常因为它只是附加属性,可以使用组合。

If there is a screen that uses only two properties of that entity, or I want to hide properties due to security concerns, I create a new view model and only retrieve the necessary data.如果有一个屏幕只使用该实体的两个属性,或者我出于安全考虑想要隐藏属性,我会创建一个新的视图模型并且只检索必要的数据。 I will reuse view models but only if the same properties are required in that other view.我将重用视图模型,但前提是其他视图中需要相同的属性。

I would share a VM between multiple view only if all properties variables and methods are used by all the views otherwise I would use inheritance and abstract base view model and if this does not solve.仅当所有视图都使用所有属性变量和方法时,我才会在多个视图之间共享 VM,否则我将使用继承和抽象基本视图模型,如果这不能解决。 Do 1 to 1做 1 对 1

TLDR: Yes (if you really want to use it and know how to use it wisely). TLDR:是的(如果您真的想使用它并知道如何明智地使用它)。

I can think of three responsibilities wanted from view model layer:我可以想到视图模型层需要的三个职责:

  1. coupling view layer & model layer together将视图层和模型层耦合在一起
  2. offering interface for unit testing提供单元测试接口
  3. separating logic into small pieces when a single page is complex当单个页面很复杂时将逻辑分成小块

The first responsibility actually conflicts with the second.第一个责任实际上与第二个责任相冲突。 Because once a view model knows (couples with) the view class to initiate, it cannot be unit tested.因为一旦视图模型知道(耦合)要启动的视图类,就无法对其进行单元测试。 Knowing the model (and its provider) class to initiate doesn't cause this problem.知道要启动的模型(及其提供者)类不会导致此问题。 However if the provider is a singleton, the unit test become less "unit".但是,如果提供者是单身人士,则单元测试将变得不那么“单元”。

When comes to the third responsibility, there is a kind of logic that I call them routing.当谈到第三个职责时,有一种我称之为路由的逻辑。 For example, after clicking on a button, the user should see the next page.例如,单击按钮后,用户应该看到下一页。 Which layer is this kind logic supposed to lie in?这种逻辑应该在哪一层? View?看法? Model?模型? Definitely NOT!当然不! It has no where to go but view model.它无处可去,只能查看模型。 Once a view model knows the class of the view model of the next page to initiate, it makes a giant view model tree to be dealt with.一旦一个视图模型知道下一个要启动的视图模型的类,它就会生成一个巨大的视图模型树来处理。 Because this happen recursively – the next page also knows the next next page.因为这是递归发生的——下一页也知道下一页。 No matter on which node in this view model tree, once a change happens, it reflects on the parent nodes.无论这个视图模型树中的哪个节点,一旦发生变化,它就会反映在父节点上。 How to deal with these reflections?如何处理这些反射? Subclassing?子类化? Remember, in the tree, a node can have hundreds of direct / indirect child nodes.请记住,在树中,一个节点可以有数百个直接/间接子节点。

Conclusion – view model is good at the third responsibility only if it drops the first.结论 - 只有当它放弃第一个责任时,视图模型才擅长第三个责任。 The only one it is really good at is the second responsibility.它唯一真正擅长的是第二个责任。 However, I see nobody mentioning it under this question.但是,我看到没有人在这个问题下提到它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM