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 框架中不相关视图的优雅解决方案是啥?的主要内容,如果未能解决你的问题,请参考以下文章