MVC Web 框架中不相关视图的优雅解决方案是啥?

Posted

技术标签:

【中文标题】MVC Web 框架中不相关视图的优雅解决方案是啥?【英文标题】:What is the elegant solution for unrelated views in MVC web frameworks?MVC Web 框架中不相关视图的优雅解决方案是什么? 【发布时间】:2011-03-24 09:19:00 【问题描述】:

我在 Rails 和 ASP.Net MVC 中遇到了以下问题。页面上通常有多个功能小部件,但一个控制器操作应该呈现页面。让我举例说明:

假设我有一个普通的电子商务网站,菜单由类别组成,而页面是显示一组产品。

对于产品,假设我在控制器上有一个动作,看起来像:

def product_list
     @products = Products.find_by_category(:name => 'lawnmowers')
end

我有一个类似的布局

<div id="menu"><%= render :partial => 'menu' %></div>
<div id="content"><%= yield %></div>

产品有观点...

<%= render :partial => 'product', :collection => @products %>

(请注意,我已将产品视图视为无关紧要)

而且菜单有部分...

<% Category.each |c| %>
   <%= render :partial => 'menu_node', :locals =>  :category => c  %>
<%  %>

我遇到问题的行是视图中的“Category.each.do”。我在视图中获取数据,而不是使用在控制器中设置和绑定的变量。它可以很容易地成为一个更复杂的方法调用来生成菜单。

我考虑过的解决方案是:

- 一个视图模型基类,它知道如何获取各种数据。但是您最终可以为网站的每个概念“部分”选择其中一个。 - 填充在每个方法顶部的局部变量(违反 DRY) - 同样的事情,但在 before_filter 调用中

这些对我来说都不是很优雅。我不禁看到这个问题,并认为按视图(而不是屏幕)的 MVP 演示者是一个更优雅的解决方案。

ASP.Net MVC 具有渲染操作(不同于 rails render :action),它确实解决了这个问题,但我不确定我对这个解决方案的看法。

想法?解决方案建议?

补充说明: 到目前为止提供的答案是很好的建议。它们适用于我给出的示例,其中菜单可能出现在每个布局中,并且显然次要于产品数据。

但是,如果明显没有二等公民怎么办?门户网站类型的站点通常有多个不相关的小部件,其中每一个都很重要。

例如,如果此页面显示天气趋势,并带有温度、湿度和降水小部件(并且每个小部件都是不同的模型和视图类型),该怎么办。

【问题讨论】:

很好的问题。我也一直在为此苦苦挣扎,因为我的应用程序具有许多“小部件”的潜力。我认为每个小部件都应该有它自己的控制器,它知道如何向它发送数据,但只是不确定如何在 ASP.NET MVC 中实现它。 我倾向于在这些场景中使用 RenderAction,但正如您所说,它远非完美。 DanP,你指的是rails还是asp.net mvc? ASP.NET MVC - 我倾向于将这些方法放在“共享”控制器中,并用 [ChildActionOnly] 来表示这些操作,以使它们的用法更清晰(呃) 【参考方案1】:

在 Rails 中,我们喜欢有一个精简控制器、厚模型的概念。所以我认为你不想在控制器中设置变量是正确的。

此外,为了以后启用更复杂的方法,我建议执行以下操作:

/app/controllers/application_controller.rb

before_filter :add_menu_nodes

def add_menu_nodes
  @menu_nodes = Category.menu_nodes(current_user)
end

/app/views/layouts/application.html.erb

<%= render :partial=>:menu, :locals=>:categories=>@menu_nodes %>

/app/models/category.rb

def self.menu_nodes(current_user)
  Category.all.order(:name)
end

这样,将来您可以根据当前用户的需要,使用更复杂的解决方案更新 Category.menu_nodes。

【讨论】:

谢谢,这是一篇不错的文章。这可能是我在导轨方面见过的最干净的解决方案。它确实假设每个布局都需要此数据。它暗示了可能并非如此的第二类数据模型(类别)。但我认为在 mvc 中你有这个问题是不可避免的。【参考方案2】:

如果我把 Ruby 弄坏了(或者误解了你的问题),请原谅我,但是有什么问题

class section_helper
    def menu( section )
        // ...
        menuBuiltAbove
    end
end

在视图中

<%= section_helper.menu( 'section' ) %>

?

【讨论】:

这不是一个坏建议,但它假定菜单是产品的二等公民。如果是菜单,我会同意。但有些情况并非如此。这就是为什么我认为 mvc 非常适合简单网站的原因,其中每个页面都有一个明确的目的,但对于门户网站类型的网站,我认为这种模式很困难。 @Tim Hoolihan 我想我明白你的问题是什么了。对于门户,我刚刚使用 jquery 对控制器进行 ajax 调用,然后更新了小部件客户端。也许这个想法有帮助? 这是一个我认为很好的实用解决方案,但我认为我正在寻找更多的模式解决方案。在性能关键的网站上,我们正在添加 http 请求。

以上是关于MVC Web 框架中不相关视图的优雅解决方案是啥?的主要内容,如果未能解决你的问题,请参考以下文章

mvc是啥,有啥用

三层架构是啥?

Web MVC框架-视图模板查找及组织

MVC是啥?

MVC和MVVM两框架是啥?

STRUTS是啥