在部分视图中包含JavaScript文件

问题描述 投票:69回答:9

[我想知道将javascript文件包含在部分视图中的最佳做法是什么。呈现后,这将最终成为我页面html中间的js include标签。从我的角度来看,这不是执行此操作的好方法。它们属于head标签,因此不应阻止浏览器一次性呈现html。

一个例子:我在“ PictureGallery”局部视图中使用了一个jQuery picturegallery插件,因为该局部视图将在多个页面上使用。仅在使用此视图并且我不想知道每个局部视图正在使用哪些插件...

时才需要加载此插件。

感谢您的回答。

javascript jquery asp.net-mvc partial-views
9个回答
28
投票

似乎与此问题非常相似:Linking JavaScript Libraries in User Controls

我将在此处重新发布该问题的答案。

我绝对不建议出于您提到的原因而将它们放入部分中。一个视图很有可能会拉入两个均引用同一个js文件的部分。在加载其余html之前,还具有加载js的性能优势。

我不知道最佳实践,但是我选择在母版页中包含所有常见的js文件,然后为一些特定于特定视图或少量视图的其他js文件定义一个单独的ContentPlaceHolder。

这是一个示例母版页,这很容易解释。

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<head runat="server">
    ... BLAH ...
    <asp:ContentPlaceHolder ID="AdditionalHead" runat="server" />
    ... BLAH ...
    <%= Html.CSSBlock("/styles/site.css") %>
    <%= Html.CSSBlock("/styles/ie6.css", 6) %>
    <%= Html.CSSBlock("/styles/ie7.css", 7) %>
    <asp:ContentPlaceHolder ID="AdditionalCSS" runat="server" />
</head>
<body>
    ... BLAH ...
    <%= Html.JSBlock("/scripts/jquery-1.3.2.js", "/scripts/jquery-1.3.2.min.js") %>
    <%= Html.JSBlock("/scripts/global.js", "/scripts/global.min.js") %>
    <asp:ContentPlaceHolder ID="AdditionalJS" runat="server" />
</body>

Html.CSSBlock和Html.JSBlock显然是我自己的扩展,但同样,它们在执行操作时具有自我解释。

然后输入我想要的SignUp.aspx视图

<asp:Content ID="signUpContent" ContentPlaceHolderID="AdditionalJS" runat="server">
    <%= Html.JSBlock("/scripts/pages/account.signup.js", "/scripts/pages/account.signup.min.js") %>
</asp:Content>

HTHs,查尔斯

Ps。这是我询问的有关缩小和串联js文件的跟进问题:Concatenate & Minify JS on the fly OR at build time - ASP.NET MVC

编辑:根据我的其他答案的要求,我对.JSBlock(a,b)的实现按要求执行]

public static MvcHtmlString JSBlock(this HtmlHelper html, string fileName)
{
    return html.JSBlock(fileName, string.Empty);
}

public static MvcHtmlString JSBlock(this HtmlHelper html, string fileName, string releaseFileName)
{
    if (string.IsNullOrEmpty(fileName))
        throw new ArgumentNullException("fileName");

    string jsTag = string.Format("<script type=\"text/javascript\" src=\"{0}\"></script>",
                                 html.MEDebugReleaseString(fileName, releaseFileName));

    return MvcHtmlString.Create(jsTag);
}

然后发生魔术的地方...

    public static MvcHtmlString MEDebugReleaseString(this HtmlHelper html, string debugString, string releaseString)
    {
        string toReturn = debugString;
#if DEBUG
#else
        if (!string.IsNullOrEmpty(releaseString))
            toReturn = releaseString;
#endif
        return MvcHtmlString.Create(toReturn);
    }

1
投票

您将脚本放置在页面底部的原因是,在尝试进行任何操作之前,请确保已加载dom。这也可以通过$(document).ready(callback);之类的东西来实现。 jQuery方法。

我同意不将嵌入式JavaScript放入html的观点。相反,我使用HTML助手来创建一个空div用作服务器指令。辅助信号为Html.ServerData(String name,Object data);

我使用此ServerData方法获取从服务器到客户端的指令。 div标签保持整洁,并且“ data-”属性为有效的html5。

对于loadScript指令,我可以在ascx或aspx中执行以下操作:

或添加另一个帮助程序,看起来更干净:

HTML输出将是:

然后我有一个jQuery方法,可以找到任何服务器数据标签:$(containsElement).serverData(“ loadScript”); //返回类似jQuery的JSON解码对象数组。

客户端可能看起来像这样:

var script = $(containselement“)。serverData(” loadScript“);$ .getScript(script.url,function(){//脚本已加载-现在可以执行脚本});

此技术非常适合需要在ajax加载的内容中加载的用户控件或脚本。我写的版本涉及到更多处理缓存脚本的问题,因此它们每满页面加载仅加载一次,并且包含回调和jQuery触发器,因此您可以在准备就绪时将其挂钩。

如果有人对此功能的完整版本(从MVC到jQuery扩展感兴趣),我很乐意更详细地展示这种技术。否则-希望它为解决这个棘手问题的人提供了一种新方法。


1
投票

今天,我已经创建了自己的解决方案,非常适合该法案。无论是好的设计,都是由大家决定的,但我认为应该以任何一种方式分享!

下面是我的HtmlExtensions类,使您可以在母版页中进行此操作:

<%=Html.RenderJScripts() %>

我的HtmlExtensions类:

public static class HtmlExtensions
{
    private const string JSCRIPT_VIEWDATA = "__js";

    #region Javascript Inclusions

    public static void JScript(this HtmlHelper html, string scriptLocation)
    {
        html.JScript(scriptLocation, string.Empty);
    }

    public static void JScript(this HtmlHelper html, string scriptLocationDebug, string scriptLocationRelease)
    {
        if (string.IsNullOrEmpty(scriptLocationDebug))
            throw new ArgumentNullException("fileName");

        string jsTag = "<script type=\"text/javascript\" src=\"{0}\"></script>";

#if DEBUG
        jsTag = string.Format(jsTag, scriptLocationDebug);
#else
        jsTag = string.Format(jsTag, !string.IsNullOrEmpty(scriptLocationRelease) ? scriptLocationRelease : scriptLocationDebug);
#endif

        registerJScript(html, jsTag);
    }

    public static MvcHtmlString RenderJScripts(this HtmlHelper html)
    {
        List<string> jscripts = html.ViewContext.TempData[JSCRIPT_VIEWDATA] as List<string>;
        string result = string.Empty; ;
        if(jscripts != null)
        {
            result = string.Join("\r\n", jscripts);
        }
        return MvcHtmlString.Create(result);
    }

    private static void registerJScript(HtmlHelper html, string jsTag)
    {
        List<string> jscripts = html.ViewContext.TempData[JSCRIPT_VIEWDATA] as List<string>;
        if(jscripts == null) jscripts = new List<string>();

        if(!jscripts.Contains(jsTag))
            jscripts.Add(jsTag);

        html.ViewContext.TempData[JSCRIPT_VIEWDATA] = jscripts;
    }

    #endregion

}

发生了什么事?上面的类将使用方法扩展HtmlHelper,以将javascript链接添加到HtmlHelper.ViewContext.TempData集合存储的集合中。在母版页的最后,我放置了<%=Html.RenderJScripts() %>,它将在HtmlHelper.ViewContext.TempData中循环jscripts集合并将其呈现到输出中。

但是有一个缺点,..您必须确保在添加脚本之前不呈现脚本。例如,如果要对css链接执行此操作,它将无法正常工作,因为您必须将它们放置在页面的<head>标签中,并且htmlhelper会在甚至添加链接之前呈现输出。


0
投票

这似乎是一个类似(尽管不完全)的问题。 Is it bad practice to return partial views that contain javascript?


0
投票

我的偏好是创建一个从您的主Site.master继承的plugin.master页面。想法是将这些插件填充到plugin.master中,并制作8个左右的页面,这些页面将使用此局部视图从plugin.master继承。


0
投票

首选方法是put scripts at the bottom,但是,如果无法避免,那么将它们放在中间是合理的。

浏览器通常并行加载各种页面元素,但是,当浏览器下载Javascript文件时,在完成Javascript下载之前,浏览器不会并行下载任何其他页面元素。这意味着您的图像以及不需要等待的图像,因此通常认为将脚本移到底部更好,但是如果您的脚本很小,那么我就不用担心。


0
投票

hejdig。

我决定暂时使用Aspnetmvc3,只是将我的javascript文件包含在局部文件中

© www.soinside.com 2019 - 2024. All rights reserved.