在部分视图中包含页面底部的JavaScript

时间:2011-11-17 20:31:17

标签: c# javascript .net asp.net-mvc asp.net-mvc-3

假设我在局部视图中有一个javascript幻灯片放映......

_Slideshow.cshtml:

@{
    ViewBag.Title = "Slide Show";
}
<div id="slides">
</div>
<script src="js/slides.min.jquery.js"></script>
<script type="text/javascript">
$(function(){
    $('#slides').slides({
        // slide show configuration...
    });
});
</script>

但我想成为一名优秀的小型Web开发人员,并确保我的所有脚本都位于页面底部。所以我会让我的* _Layout.cshtml *页面看起来像这样:

_Layout.cshtml:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/css/global.css")" rel="stylesheet" type="text/css" />
</head>
<body>
    <div id="wrapper">
    @RenderBody
    </div>
    <!-- Being a good little web developer, I include my scripts at the BOTTOM, yay!
    -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript"></script>
</body>
</html>

但是UH OH!我现在该怎么做,因为我的幻灯片脚本最终超出了我的jQuery包含范围?!如果我想在每个页面上播放幻灯片,这不会是什么大不了的事,但我只希望幻灯片放映部分视图在某个页面上呈现,并且......我希望我的脚本在底部!怎么办?

2 个答案:

答案 0 :(得分:9)

您可以在布局页面中为这样的脚本定义一个部分:

<body>
    <div id="wrapper">
    @RenderBody
    </div>
    <!-- Being a good little web developer, I include my scripts at the BOTTOM, yay!
    -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript"></script>
    @RenderSection("myScripts")
</body>

然后在您的页面上定义该部分的内容:

@{
    ViewBag.Title = "Slide Show";
}
<div id="slides">
</div>
@section myScripts { //put your scripts here
    <script src="js/slides.min.jquery.js"></script>
    <script type="text/javascript">
    $(function(){
        $('#slides').slides({
            // slide show configuration...
        });
    });
    </script>
}

然后,当页面呈现时,它会将您的部分中的所有内容添加到应该放置在布局页面上的位置(在这种情况下,位于底部)。

答案 1 :(得分:3)

注意:已接受的解决方案无法正常工作 部分视图,如问题所示。

问题

在正常流程中,您可以使用@section SectionName {}声明从ActionResult上的父视图内部定义特定部分的内容。当该视图最终插入其LayoutPage时,它可以调用RenderSection将这些内容放在页面内的任何位置,允许您定义一些内联JavaScript,可以在任何核心之后在页面底部呈现和解析像这样依赖的图书馆:

Layout > Full View

如果您希望能够在部分视图中重用整个页面视图,则会出现问题。也许您还想从另一个页面内部将视图重新用作窗口小部件或对话框。在这种情况下,只要您在父视图中将@Html.EditorFor@Html.Partial的调用置于此处,就会完整呈现完整的部分视图:

Layout > Parent View > Partial View

根据MSDN Docs on Layouts with Razor Syntax

  
      
  • 视图中定义的部分仅在其直接布局页面中可用。
  •   
  • 无法从视图系统的局部视图,视图组件或其他部分引用节。
  •   
  • 内容页面中的正文和所有部分都必须由布局页面
  • 呈现   

在这种情况下,将定义到局部视图中的脚本放到页面底部变得很棘手。根据文档,您只能从布局视图中调用RenderSection,并且无法从局部视图内部定义@section内容,因此所有内容都会被集中到同一区域,您的脚本将被渲染,解析,并从HTML页面的中间运行,而不是在它可能依赖的任何库之后的底部。

解决方案

有关将部分视图中的部分注入页面的多种方法的完整讨论,我将从StackOverflow上的以下两个问题开始:

其中不同的解决方案在支持嵌套,排序,多脚本支持,不同内容类型,调用语法和可重用性方面存在差异。但无论你如何分割它,几乎任何解决方案都必须完成两个基本任务:

  1. 从任何页面,部分视图或模板中逐渐构建脚本对象到您的请求,可能会利用某种HtmlHelper扩展来实现可重用性。
  2. 将该脚本对象渲染到布局页面上。由于布局页面实际上是最后渲染的,因此只是将我们构建的对象发送到母版页上。
  3. 此处a simple implementation Darin Dimitrov

    添加帮助程序扩展方法,这些方法允许您将任意脚本对象构建到ViewContent.HttpContext.Items集合中,然后再获取并呈现它们。

    <强> Utilities.cs

    public static class HtmlExtensions
    {
        public static MvcHtmlString Script(this HtmlHelper htmlHelper, Func<object, HelperResult> template)
        {
            htmlHelper.ViewContext.HttpContext.Items["_script_" + Guid.NewGuid()] = template;
            return MvcHtmlString.Empty;
        }
    
        public static IHtmlString RenderScripts(this HtmlHelper htmlHelper)
        {
            foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
            {
                if (key.ToString().StartsWith("_script_"))
                {
                    var template = htmlHelper.ViewContext.HttpContext.Items[key] as Func<object, HelperResult>;
                    if (template != null)
                    {
                        htmlHelper.ViewContext.Writer.Write(template(null));
                    }
                }
            }
            return MvcHtmlString.Empty;
        }
    }
    

    然后你可以在你的应用程序中使用这样的

    部分视图中构建此类脚本对象,如下所示:

    @Html.Script(
        @<script>
             $(function() {
                 $("#@Html.IdFor(model => model.FirstName)").change(function() {
                     alert("New value is '" + this.value + "'");
                 });
             })
         </script>
    )
    

    然后在 LayoutPage 中的任意位置渲染它们,如下所示:

    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
    @Html.RenderScripts()
    
相关问题