【问题标题】:MVC Razor @foreachMVC 剃刀 @foreach
【发布时间】:2012-06-30 23:21:57
【问题描述】:

我听说在视图中使用 @foreach 是不行的。意思是,视图中不应该有任何逻辑。 @foreach 的逻辑应该在哪里的最佳实践是什么?

    @foreach.. 

【问题讨论】:

标签: asp.net-mvc razor


【解决方案1】:

@foreach 的逻辑应该在哪里的最佳实践是什么?

无处可去,只是摆脱它。您可以使用编辑器或显示模板。

例如:

@foreach (var item in Model.Foos)
{
    <div>@item.Bar</div>
}

完全可以用显示模板代替:

@Html.DisplayFor(x => x.Foos)

然后您将定义相应的显示模板(如果您不喜欢default one)。因此,您将定义一个可重用模板~/Views/Shared/DisplayTemplates/Foo.cshtml,该模板将由框架自动为 Foos 集合 (IEnumerable&lt;Foo&gt; Foos { get; set; }) 的每个元素呈现:

@model Foo
<div>@Model.Bar</div>

显然,完全相同的约定适用于编辑器模板,如果您想显示一些输入字段以允许您编辑视图模型,而不是仅将其显示为只读,则应使用这些约定。

【讨论】:

  • @DarinDimitrov 如果它是一个严格的 MVC 模型,那么这是正确的,但是如果出现需要循环的集合不在模型中的情况,我认为使用 foreach 没有问题
  • @NicholasKing,这种情况绝不应该出现。除了控制器操作传递的视图模型中存在的内容之外,视图不应触及任何其他内容。如果它不在视图模型中,那么如果视图需要它,你应该把它放在那里。这正是视图模型的用途。
  • @MihaiLabo,是的,我就是这么说的。
  • 如果集合中元素的类型不足以确定显示怎么办?例如,我的模型有一组字符串,但有时我希望每行有一个字符串,而在另一种情况下,我希望它们用逗号分隔?
  • 那么,foreach 到底有什么问题?至少一个显示模板(尽管是一种完全可以接受的方法,无论如何)需要渲染一个新的视图,这不是免费的。大多数情况下,它不会显着影响您的网站加载时间,但做得足够多,可能会导致性能下降。围绕一点 HTML 的foreach 几乎是即时的。就像我说的那样,这两种方式都不是什么大不了的事,但如果有的话,使用foreach 的参数for
【解决方案2】:

当人们说不要在视图中放置逻辑时,他们通常指的是业务逻辑,而不是渲染逻辑。以我的拙见,我认为在视图中使用 @foreach 非常好。

【讨论】:

  • 同意。让我想起了旧的语义 HTML 辩论,最终导致人们尝试使用 div 和 CSS 为实际的表格数据创建一个“表格”,因为它们是如此反表格。
  • 我同意。人类不擅长误导。我真的需要一个带有新视图的新文件夹,只是为了在我的视图模型的列表中显示内容吗?
  • 不会使用 div/css 创建表格数据视图来创建响应式视图吗?
【解决方案3】:

我在发送包含实体列表的实体时使用@foreach(例如,在 1 个视图中显示 2 个网格)

例如,如果我将包含 Foo1(List&lt;Foo1&gt;)Foo2(List&lt;Foo2&gt;) 的实体 Foo 作为模型发送

我可以参考第一个列表:

@foreach (var item in Model.Foo.Foo1)
{
    @Html.DisplayFor(modelItem=> item.fooName)
}

【讨论】:

    【解决方案4】:

    回复@DarinDimitrov 关于我在剃刀视图中使用 foreach 的案例。

    <li><label for="category">Category</label>
            <select id="category">
                <option value="0">All</option>
                @foreach(Category c in Model.Categories)
                {
                    <option title="@c.Description" value="@c.CategoryID">@c.Name</option>
                }
            </select>
    </li>
    

    【讨论】:

    • 哇,伙计,你会在视图中写这样的东西吗?为什么不写一个可重用的自定义助手 à la Html.DropDownListFor 来简单地考虑标题?这很简单,不会将您的观点变成意大利面条代码:stackoverflow.com/a/7938038/29407
    • @DarinDimitrov 是的,我们在一个非常敏捷的环境中工作,这意味着像这样的场景有时会阻止我们使用 DropDownFor 之类的东西,因为我们并不总是有明确定义的需求。我相信在这种情况下,下拉菜单最初不需要“全部”,然后它确实需要,但仅在视图上的一个 DropDown 中。由于此页面使用 ajax 来更新其不是严格的 MVC 模式,因此您无法根据要求将产品上传到所有类别。不理想,但有时不可避免。
    • 也许更好的例子是使用它来呈现选择列表中的optgroup 元素,因为在 HtmlHelpers 中不支持它。如果您只需要在选择列表中添加一个额外的项目,有更好的方法来实现它,然后仍然使用帮助器。
    • 那不是我对敏捷的定义——我必须同意@DarinDimitrov
    【解决方案5】:

    The answer 在使用重载指示模板 @Html.DisplayFor(x =&gt; x.Foos, "YourTemplateName) 时将不起作用。

    似乎是这样设计的,see this case。此外,框架给出的异常(关于类型不符合预期)非常误导并在第一次尝试时愚弄了我(感谢@CodeCaster)

    在这种情况下你必须使用@foreach

    @foreach (var item in Model.Foos)
    {
        @Html.DisplayFor(x => item, "FooTemplate")
    }
    

    【讨论】:

    • 这个答案是由从事 MVC 工作的人写的,所以我猜他们知道他们在说什么。 MVC 将迭代IEnumerable&lt;T&gt; 并为每个元素调用T 类型的模板。
    • 关于您的编辑:要么是您的代码错误,要么是该特定 MVC 版本中的错误(在 5.2.2 中它适用于我)。它应该按照接受的答案中的描述工作。如果你愿意,不要说它是错误的,而是提出你自己的问题。
    • @CodeCaster 我相信我的回复为该特定案例增加了一些提示(它浪费了我一些时间来弄清楚出了什么问题)。您能否添加一些解释以保持反对票? (顺便说一句,感谢您抽出宝贵时间,只是想弄清楚事情的真相)
    • 我认为这不是一个好的答案,因为它没有验证错误,这有助于世界上的谣言,如“A DisplayTemplate 无法迭代” - 它应该是,所以它应该工作.如果确实没有,请提交错误并打开一个单独的问题,在其中重现问题并提及此特定版本,而不是在处理通常应该发生的情况的问答中。
    • @CodeCaster 在我了解了我的具体情况(我更改了整个帖子)之后,我同时进行了另一次编辑。在我上次的编辑中,我指出了当接受的答案不适用于与由同一个人回答的相关问题的备份链接时的确切条件,证明这是设计使然,而不是错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-12
    • 2011-06-09
    • 2011-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多