MVC:将模型/模型数据传递给控制器​​的视图?

时间:2009-09-03 02:17:14

标签: model-view-controller language-agnostic design-patterns

如果视图需要从模型访问数据,您认为控制器应该:

a)将模型传递给视图
b)将模型的数据传递给视图
c)两者;它不应该是控制器的关注点。让视图直接访问模型以检索数据。只让控制器提供视图所需的一些参数来过滤模型中的数据 d)这取决于具体情况 e)以上都不是,但是[...]

由于

在评论中对用户删除的答案进行了一些辩论之后,这可能需要澄清。我对MVC架构的看法偏向于Zend Framework(php),其中默认情况下控制器中的操作具有分配给它的默认视图。因此,模型不是决定哪个视图是合适的,而是控制器。你觉得模型应该决定哪种观点合适吗?我认为让视图基于模型构建的唯一方法是让控制器将模型传递给视图。是否还有其他技术可以让视图在不涉及控制器的情况下访问模型?或者让控制器将模型传递给视图是否完美,以便可以根据模型属性构建视图?

7 个答案:

答案 0 :(得分:10)

e)以上都不是;传递视图优化的“ViewModel”。

ASP.NET MVC中的示例: -

public ActionResult Details(int id)
{
  Product p = ProductService.GetProductById(id);

  if(p == null) { return RedirectToAction("Index"); }

  ProductViewModel model = new ProductViewModel(p);
  return View(model);
}

a)和b)“将做”受制于d)。从来没有c)。

通常,ViewModel只封装模型(如果没有复杂的事情,您的视图可以直接通过ProductViewModel.Product访问模型)。如果视图需要对模型执行任何复杂操作,那么ViewModel有责任这样做,而不是Controller或View的责任。

这可以让您的顾虑保持良好和隔离。您的控制器并不关心View所需的具体数据(除了它呈现产品的某些细节之外),或者尤其是您的View需要该数据的格式。您的View不依赖于您的View的实现细节。模型。您的模型不必关心它的被查看方式。如果您有两个视图呈现产品(例如,创建,编辑,摘要,更多详细信息等),那些视图可以具有不同的ViewModel,以仅公开每个特定视图所需的数据,因此您的视图不依赖于彼此。可爱的:))

从各种观点进一步阅读: -

http://www.thoughtclusters.com/2007/12/datamodel-and-viewmodel/

http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx

http://www.nikhilk.net/Silverlight-ViewModel-MVC.aspx

我认为ViewModel是一个特别的.NET东西,但我认为没有理由为什么这个模式不能在PHP中使用。

希望这有帮助。

答案 1 :(得分:2)

理想情况下,它应该“将模型的数据传递给视图”,因此视图不需要知道模型的任何显式结构,因此更具可重用性和设计友好性。

但实际上,“将模型传递给视图”就可以了。大多数时候你都需要一个新的视图,因为客户永远不会分享喜欢的颜色(如果你知道我的意思:-)所以视图的可重用性并不能证明从模型复制数据需要很多繁琐的代码观点。

您应该更关注的是控制器本身的模块化,因为许多网站都共享共同的功能(控制器),如网络论坛或新闻列表,但不是外观(视图)

答案 2 :(得分:2)

这是我知道,但我正在处理我正在处理的项目中的这个问题。我开始时a) - 为了简单起见 - 现在遇到了路障。

我正在研究这种方法:

e)以上都不是;传递视图优化的“ViewModel”。

因为它避免使您的模型类(其实例是“事务对象”)和您的视图膨胀。例如,您可能需要渲染具有特定小数位数的数字(这是我现在遇到的问题)。

使用中间的“ViewModel”这很容易 - 你只需编写相关的ViewModel“getXXX”方法来返回格式化的数字。

如果您只是将模型直接传递到视图中,则每次使用此图时都需要在视图中指定它(与DRY​​相反 - 不要自己重复),或者替换地,将渲染方法添加到视图中模型类(仅针对一个目的的类)。

干杯

答案 3 :(得分:1)

a)将模型传递给视图

否则控制器通过筛选模型来操纵视图。这是“b)将模型的数据传递给视图”中会发生的情况。 b)选项在纯MVC模式中甚至没有意义。毕竟,模型是数据。如果更改模型以进行消耗,则会应用视图,无论您是选择在控制器中执行此操作还是将其作为控制器功能传递出去。当你有不同的观点时会发生什么?控制器是否以不同方式屏蔽其数据?您很快就会有两个关于模型,控制器子视图和视图本身的视图。

答案 4 :(得分:1)

对我来说就是e)。

正如这里已经提到的,理想情况下视图和模型是分离的。我更喜欢实现这个的方法是为模型创建一个viewHelper。这具有视图可用于获取数据的API。现在视图不受模型中的更改的影响,并且视图不需要“获取”模型的内部。它们被viewHelper隐藏起来。

示例:

class Post {
    public function export(ViewHelper $helper) {} // I try to avoid getters when I can
}

class PostViewHelper {
    public function getTitle($parameters) {} // title of current post in the loop
}

class PostView {
    private $helpers = array();
    public function loadTemplate($path) {}
    public function addHelper(ViewHelper $helper, $name) {}
    public function __get($key) {} // if exists $this->helper[$key] etc
}

在模板中

<h1><?php $this->post->getTitle(); ?></h1>

您可能希望以不同方式实现此目的。但我的观点是视图和模型如何解耦,引入了一个中间viewHelper,它创建了视图/模板API。

答案 5 :(得分:1)

我认为这并不复杂。 a或b。

控制器的工作是管理关系。它查找模型和视图,并提供查看完成其工作所需的所有模型数据。而已。 MVC没有规定数据的确切形式。

(a)从简单开始。将模型对象直接传递给视图是很自然的。如果您有关于Foo的页面,请传递Foo。

(b)但有时 - 并且有时 - 你创建一个值对象/ DTO来将数据提供给视图(上面称为ViewModel)。 在视图与本机模型之间不匹配时执行此操作,例如摘要视图。如果视图显示1,000,000个对象的摘要,则不希望将视图交给模型对象;您希望将视图提供1,000,000个对象的摘要。

确切的实现实际上取决于您使用的语言和框架。但我认为这些指导方针是一个良好的开端。

答案 6 :(得分:0)

呃,b。

我真的没有看到a和b之间的区别,除了你将如何传递数据的技术性。

通常使用模型中的一些数据将数据映射传递给视图