从部分填充剃刀部分

IT技术 javascript asp.net-mvc-3 razor
2021-03-11 04:47:18

我尝试这样做的主要动机是获取仅页面底部的部分需要的 Javascript 和其余的 Javascript,而不是在呈现部分的页面中间。

这是我正在尝试做的一个简化示例:

这是在正文之前带有脚本部分的布局。

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />    
</head>

<body>
    @RenderBody()
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
    @RenderSection("Scripts", false)
</body>
</html>

这是使用此布局的示例视图。

<h2>This is the view</h2>

@{Html.RenderPartial("_Partial");}

@section Scripts {
<script type="text/javascript">
        alert("I'm a view.");
</script>
}

这是从视图中呈现的部分。

<p>This is the partial.</p>

@* this never makes it into the rendered page *@
@section Scripts {
<script type="text/javascript">
    alert("I'm a partial."); 
</script>
}

在此示例中,视图中指定的标记被放置到部分中,但部分中的标记未放置。是否可以使用 Razor 从局部视图填充部分?如果没有,还有哪些其他方法可以获取仅页面底部的部分需要的 Javascript,而无需全局包含它?

6个回答

我处理这个问题的方法是为 HtmlHelper 类编写几个扩展方法。这允许局部视图说他们需要一个脚本,然后在布局视图中写入标记我调用我的助手方法以发出所需的脚本

以下是辅助方法:

public static string RequireScript(this HtmlHelper html, string path, int priority = 1)
{
    var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
    if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
    if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
    return null;
}

public static HtmlString EmitRequiredScripts(this HtmlHelper html)
{
    var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
    if (requiredScripts == null) return null;
    StringBuilder sb = new StringBuilder();
    foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
    {
        sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
    }
    return new HtmlString(sb.ToString());
}
public class ResourceInclude
{
    public string Path { get; set; }
    public int Priority { get; set; }
}

一旦你有了它,你的局部视图只需要调用@Html.RequireScript("/Path/To/Script").

并在布局视图的头部部分调用@Html.EmitRequiredScripts().

这样做的一个额外好处是它允许您清除重复的脚本请求。如果您有多个需要给定脚本的视图/部分视图,您可以放心地假设您只会输出一次

听起来有些不对劲,布莱恩。在过去一年左右的时间里,我广泛使用了这个解决方案,并且运行良好。也许发布一个包含您问题详细信息的新问题并在此处链接网址
2021-04-19 04:47:18
在拔出我的大部分头发后刚刚遇到了这个解决方案 - 优秀的解决方案......
2021-04-27 04:47:18
我无法让这个解决方案起作用。似乎 EmitRequiredScripts() 在任何部分视图调用 RequireScript() 之前被调用。难道我做错了什么?
2021-05-02 04:47:18
部署新版本的应用程序时,这是否有任何缓存破坏支持?开箱即用的@scripts.Render() 方法在构建时生成的末尾粘贴一个 URL 参数,以便在部署新版本时浏览器强制获取最新版本。
2021-05-09 04:47:18
优雅干净的解决方案。+1
2021-05-14 04:47:18

部分视图不能参与其父视图的部分。

这是我怀疑的。谢谢。
2021-04-17 04:47:18
@Shimmy:您应该使用资源管理系统,例如 Cassette。
2021-04-18 04:47:18
谢谢你。我会调查一下。
2021-04-21 04:47:18
@JohnBubriski 在 Razor 2 中有。不知道上一个。版本。
2021-05-01 04:47:18
@SLaks,为什么是这样设计的?在我的场景中,我有一个部分是横幅旋转器,我希望它的脚本/样式仅在打开时加载,为什么内联加载它不好?
2021-05-04 04:47:18

你可以有第二个部分,只负责注入必要的 javascript。@if如果需要,可以周围放置几个脚本

@model string
@if(Model == "bla") {
    <script type="text/javascript">...</script>
}

@else if(Model == "bli") {
    <script type="text/javascript">...</script>
}

这显然可以稍微清理一下,但是,在Scripts您的视图部分:

@section Scripts
{
    @Html.Partial("_Scripts", "ScriptName_For_Partial1")
}

同样,它可能不会赢得美容奖,但它会起作用。

这与我最终所做的非常接近。它绝对不漂亮,但它有效。唯一的缺点是您无法通过 ajax 调用获取部分内容并包含 JS。我认为从长远来看,我最终将使用 jQuery 模板进行重构,并且只从我的控制器发送 JSON,而不是在服务器端构建 html。
2021-04-29 04:47:18
@one.beat.customer - 我一直在使用 underscore 的模板,因为我也使用 Backbone,但我正在考虑从 Twitter 切换到 Hogan 库或从 Nodejitsu 切换到 Plates。两者都有相当不错的功能。
2021-04-30 04:47:18
@CraigM 这也是我要去的地方。MVC 是合法的,但(对我而言)使用客户端模板(我正在研究 Backbone.js)然后从 API 推/拉更有意义。
2021-05-15 04:47:18

更优雅的方法是将部分视图脚本移动到单独的文件中,然后在视图的脚本部分呈现它:

<h2>This is the view</h2>

@Html.RenderPartial("_Partial")

@section Scripts
{
    @Html.RenderPartial("_PartialScripts")

    <script type="text/javascript">
        alert("I'm a view script.");
    </script>
}

局部视图 _ Partial.cshtml

<p>This is the partial.</p>

部分视图 _ PartialScripts.cshtml仅包含脚本:

<script type="text/javascript">
    alert("I'm a partial script!");
</script>
这不像其他答案中建议的一些扩展方法或插件那样自动,但它确实具有简单明了的优点。它喜欢它。
2021-05-01 04:47:18

安装Forloop.HtmlHelpers nuget 包 - 它添加了一些帮助程序来管理部分视图和编辑器模板中的脚本。

在布局中的某个地方,您需要调用

@Html.RenderScripts()

这将是任何脚本文件和脚本块将在页面中输出的地方,因此我建议将其放在布局中的主要脚本之后和脚本部分之后(如果有的话)。

如果您使用捆绑的 Web 优化框架,则可以使用重载

@Html.RenderScripts(Scripts.Render)

以便此方法用于写出脚本文件。

现在,只要您想在视图、局部视图或模板中添加脚本文件或块,只需使用

@using (Html.BeginScriptContext())
{
  Html.AddScriptFile("~/Scripts/jquery.validate.js");
  Html.AddScriptBlock(
    @<script type="text/javascript">
       $(function() { $('#someField').datepicker(); });
     </script>
  );
}

如果多次添加,帮助程序确保仅呈现一个脚本文件引用,并且还确保脚本文件按预期顺序呈现,即

  1. 布局
  2. 部分和模板(按照它们在视图中出现的顺序,从上到下)