代码之家  ›  专栏  ›  技术社区  ›  Peter

在部分视图中包含javascript文件

  •  69
  • Peter  · 技术社区  · 17 年前

    我想知道在局部视图中包含javascript文件的最佳实践是什么。一旦呈现,它将作为JS include标记出现在页面的HTML中间。在我看来,这不是一个很好的方法。它们属于head标签,因此不应阻止浏览器一次性呈现HTML。

    一个例子: 我正在“PictureGallery”部分视图中使用jQuery PictureGallery插件,因为此部分视图将用于多个页面。仅当使用此视图时需要加载此插件,并且 我不想知道每个部分视图使用的插件…

    谢谢你的回答。

    8 回复  |  直到 15 年前
        1
  •  28
  •   Community Mohan Dere    9 年前

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

    我把那个问题的答案转寄到这里。

    我绝对不建议把它们放在党派里面,因为你提到的正是这个原因。一个视图很可能会拉入两个引用同一个JS文件的部分。在加载其余的HTML之前,您也会遇到加载JS的性能问题。

    我不知道最佳实践,但我选择在masterpage中包含任何常见的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显然是我自己的扩展,但同样,它们在做什么方面是不言自明的。

    然后在say 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>
    

    查尔斯

    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);
        }
    
        2
  •  1
  •   jhorback    16 年前

    将脚本放在页面底部的原因是为了确保在尝试任何操作之前已经加载了DOM。这也可以通过类似于$(document).ready(callback);jquery方法来实现。

    我分享了在HTML中不放置嵌入式JavaScript的观点。相反,我使用HTML助手创建一个空的DIV,用作服务器指令。helper sig为html.serverdata(字符串名称、对象数据);

    我使用这个serverdata方法来获取从服务器到客户机的指令。DIV标记使其保持干净,“data-”属性是有效的HTML5。

    对于loadscript指令,我可以在ascx或aspx中执行类似的操作:

    <%= Html.ServerData("loadScript", new { url: "pathTo.js" }) %>
    

    或者添加另一个助手来执行此操作,使其看起来更干净:

    <%= Html.LoadScript("~/path/to.js") %>

    HTML输出将是:

    <div name="loadScript" data-server="encoded json string">

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

    客户可能看起来像这样:

    var script = $(containingelement").serverData("loadScript");
    $.getScript(script.url, function () {
        // script has been loaded - can do stuff with it now
    });
    

    这种技术对于需要在Ajax加载内容中加载的用户控件或脚本非常有用。我编写的版本在处理缓存脚本方面有点复杂,因此它们在每一整页加载时只加载一次,并且包含回调和jquery触发器,这样您就可以在准备就绪时钩住它。

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

        3
  •  1
  •   Peter    15 年前

    今天,我已经创建了自己的解决方案,完全符合账单要求。无论是好的设计还是不好的设计,都是由你们大家来决定的,不过我想我还是应该分享一下!

    下面是我的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 并将其呈现到输出。

    但也有一个缺点。在添加脚本之前,必须确保不呈现它们。例如,如果您想为CSS链接执行此操作,它将不起作用,因为您必须将这些链接放置在 <head> 页面的标记和htmlhelper将在添加链接之前呈现输出。

        4
  •  0
  •   Community Mohan Dere    9 年前

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

        5
  •  0
  •   Pita.O    17 年前

    我的首选项是创建从您的主网站.master继承的plugin.master页。这样做的目的是将这些插件塞进plugin.master,并创建8个左右的页面,这些页面将使用此部分视图从plugin.master继承。

        6
  •  0
  •   aleemb    17 年前

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

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

        7
  •  0
  •   LosManos    15 年前

    HeigDig.

    在玩aspnetmvc3的时候,我决定暂时只将我的javascript文件包含在

    <script src=“@url.content(”~/scripts/user/list.js“)”type=“text/javascript”></script>

    然后,该JS文件特定于my/user/list.schtml文件。

        8
  •  -1
  •   erikkallen    17 年前

    MVC的设计者在阻止我们使用代码时遇到了很多麻烦,但是通过创建一个名为<viewname>.aspx.cs的文件并相应地修改aspx页的inherits属性,仍然可以获得它们。

    我想说,放置include的最佳位置应该在codebehind中的页面加载处理程序中(使用page.clientscript.registerclientscriptInclude)。