MVC3 布局页、视图、RenderPartial 和将脚本文件放入头部(来自局部视图)

13

我有一个布局页面。

<head>
    @RenderSection("HeaderLast", required: false)
</head>
一个视图
@section HeaderLast
{
    <script src="@Url.Content("~/Scripts/knockout-1.2.0.js")"
                            type="text/javascript"></script>
}

<div id="profile-tab">
        @{ Html.RenderPartial("_userProfile"); }
</div>

还有一个局部视图

@section HeaderLast
{
    <script type="text/javascript">
        alert('test');
    </script>
}

<div......

我想这件事情肯定不是那么简单,有没有一种适当的方式可以直接处理,或者总是需要一些中介来传递ViewData,并手动使内容冒泡到布局页面?

悬赏开始:将奖励给提供最佳解决方案的人。如果没有答案,我将授予@SLaks原始回答此问题。


这个部分需要在实际页面中定义,以便框架知道它已被处理了,不是吗? - user156888
2
我不理解这个问题 - 你想要做什么,你想要消除什么? - Danny Tuppeny
@cvista 这个部分在LayoutPage中定义,因为那里有头部。@Danny Tuppeny我想从局部视图中访问头部。 - Chris Marisic
我不是指已定义 - 我是指已实现 - 你的 @section 在 ctrl 中。 - user156888
@Chris Marisic,你找到解决方案了吗?我也有同样的情况要处理。 - Prasad
@Prasad 我还没有,我在这个问题上放了一个赏金,希望能看到一些有趣的想法/项目。目前在我的个人项目中,我只是暂时将JavaScript内联嵌入其中。 - Chris Marisic
5个回答

8

在局部视图中,您无法定义部分内容。

相反,您可以将Javascript放入ViewBag中,然后在布局页面中发出ViewBag中找到的任何Javascript。


有人为此制作了NuGet吗?这是一个相当明显的设计缺陷。 - Chris Marisic
@Chris - 你为什么认为这是一个明显的设计缺陷? - JasCav
1
@JasCav:如果一个部分需要自己的CSS,则没有很好的方法来使其呈现。 - SLaks
4
我同意Chris和SLaks的看法,这很烦人。我希望能够以模块化方式开发局部视图,并具有自己的css和js,并且在呈现局部视图时有一种机制可以正确地将css和js放置到DOM中。 SLaks,你的解决方案有示例吗? - Patrick Lee Scott

6

@JasCav: 如果一个局部需要自己的CSS,它没有好的方法来渲染它。

如果这是使用它的原因,那么很可能是有意为之。

你不想要一个单独的CSS文件x局部/帮助程序。记住,每个单独的CSS文件意味着从服务器获取它的单独请求,因此会影响到渲染页面所需的时间,增加了额外的往返。

此外,你不想从局部/帮助程序向HTML发出直接的CSS。相反,你希望它具有适当的钩子,可以在站点的CSS文件中定义所有外观。

你可以使用与CSS可用的相同钩子来激活涉及元素的自定义JavaScript行为,当启用JavaScript时。

最后,也许你需要的不是Partial View,而是一个额外的Layout,用于一些页面。采用这种方法,你将拥有:

  • 主Layout,像你现在可能已经设置的_ViewStart自动设置。这定义了像样本中的那样的部分。
  • 一个子Layout页面。在这里,你需要为这些视图提供额外的html、css、js。这使用@RenderBody()和@section SomeSection {}来结构化你的常见额外布局。
  • 一些指向子Layout的视图,以及其他使用默认主Layout的视图。

如何将额外的数据传递给子Layout超出了问题的范围,但你有几个选项。比如为你的实体设置一个公共基础;使用ViewBag或调用Html.RenderAction来获取与布局中共享动态元素相关的共享逻辑。


使用多个布局页面似乎会成为一种噩梦般的维护练习。 - Chris Marisic
1
我已经使用了这种方法,随着代码的发展,它的流程非常顺畅。我具体的做法是“调用Html.RenderAction来获取与布局中共享动态元素相关的共享逻辑”。我非常喜欢它,因为它比让部分视图执行Html.RenderAction要好得多;必须处理与不相关操作中的额外数据以使其流向部分视图,或者使用无类型的方法传递数据。你的示例太泛泛而谈,很难说清楚,挑战一下那个片段属于部分视图的想法/也许它真的是某个常见布局的一部分。 - eglasius
请注意,真正的部分视图通常属于我回答中的第一种情况,因此也要考虑该脚本/CSS是否应从该部分视图调用,还是属于站点级别的CSS/JS文件,并与之连接。话虽如此,现实中存在太多情况,您可能会遇到这样的情况,您正在尝试做的就是最佳方法。 - eglasius
这与本问题无关,但我开始考虑通过将真正的视图作为JavaScript文件来实现半革命性的事情,因此始终存在view.cshtml和view.js.cshtml,然后将所有组件JavaScript编写为部分视图或在部分视图中使用部分视图或部分内容,并在我的js视图中使用render partial。我倾向于看看是否可以找到一种定义部分并在js视图中呈现该部分的部分视图的方法,以便我的小部件类型组件都是自包含的,只需要提升到视图和view.js中。 - Chris Marisic
另一个想法是消除需要单独的view.js.cshtml文件,实际上在我的视图中定义一个javascript部分,然后找出如何为script src="view.js"提供该部分的内容。 - Chris Marisic

1

看起来在SO上有一个类似的问题 - 如何从部分视图呈现JavaScript到MasterLayout部分?

不幸的是,在部分视图中没有声明部分的可能性。这是因为RenderPartial最终呈现完全独立的视图页面。虽然有一个解决方法,但有点丑陋。但如果使用强类型模型而不是ViewData,则可以看起来更好。

基本上,您需要跟踪调用RenderPartial的视图的引用,并在传递给该视图的对象上使用DefineSection方法将数据推送到该视图。

更新:还有一篇博客文章介绍如何处理RenderSection,您可能会发现有用。


你发布的解决方案线程确实有一些潜力,但我还需要查看其他链接。 - Chris Marisic

1

0
作为对我的问题的跟进,JavaScript/CSS 组合/缩小工具 Cassette 支持此功能,允许您将所需的 JavaScript 和其他资产分隔开来,以用于部分视图。
我购买了一个网站许可证,并在所有的 MVC 应用程序中使用它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接