[我想知道将javascript文件包含在部分视图中的最佳做法是什么。呈现后,这将最终成为我页面html中间的js include标签。从我的角度来看,这不是执行此操作的好方法。它们属于head标签,因此不应阻止浏览器一次性呈现html。
一个例子:我在“ PictureGallery”局部视图中使用了一个jQuery picturegallery插件,因为该局部视图将在多个页面上使用。仅在使用此视图并且我不想知道每个局部视图正在使用哪些插件...
时才需要加载此插件。感谢您的回答。
似乎与此问题非常相似: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);
}
您将脚本放置在页面底部的原因是,在尝试进行任何操作之前,请确保已加载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扩展感兴趣),我很乐意更详细地展示这种技术。否则-希望它为解决这个棘手问题的人提供了一种新方法。
今天,我已经创建了自己的解决方案,非常适合该法案。无论是好的设计,都是由大家决定的,但我认为应该以任何一种方式分享!
下面是我的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会在甚至添加链接之前呈现输出。
这似乎是一个类似(尽管不完全)的问题。 Is it bad practice to return partial views that contain javascript?
我的偏好是创建一个从您的主Site.master继承的plugin.master页面。想法是将这些插件填充到plugin.master中,并制作8个左右的页面,这些页面将使用此局部视图从plugin.master继承。
首选方法是put scripts at the bottom,但是,如果无法避免,那么将它们放在中间是合理的。
浏览器通常并行加载各种页面元素,但是,当浏览器下载Javascript文件时,在完成Javascript下载之前,浏览器不会并行下载任何其他页面元素。这意味着您的图像以及不需要等待的图像,因此通常认为将脚本移到底部更好,但是如果您的脚本很小,那么我就不用担心。
hejdig。
我决定暂时使用Aspnetmvc3,只是将我的javascript文件包含在局部文件中