llamar - Incluir archivo JavaScript en vistas parciales
llamar funcion javascript desde otro archivo. js (8)
El enfoque preferido es colocar las secuencias de comandos en la parte inferior , sin embargo, si no puede evitar eso, entonces es razonable ponerlas en el medio.
Los navegadores generalmente cargan los diversos elementos de la página en paralelo, sin embargo, mientras el navegador descarga el archivo Javascript, no descargará ningún otro elemento de la página en paralelo hasta que el Javascript finalice la descarga. Esto significa que sus imágenes y lo que no tendrá que esperar, por lo que generalmente se considera mejor mover las secuencias de comandos en la parte inferior, pero si su secuencia de comandos es pequeña, entonces no me preocuparía.
Me pregunto cuál es la mejor práctica para incluir archivos JavaScript dentro de vistas parciales. Una vez renderizado, esto terminará como una etiqueta js include en el medio del html de mi página. Desde mi punto de vista, esta no es una buena forma de hacer esto. Pertenecen a la etiqueta principal y, como tales, no deberían impedir que el navegador muestre el html de una vez.
Un ejemplo: estoy usando un complemento de jquery picturegallery dentro de una vista parcial ''PictureGallery'' ya que esta vista parcial se usará en varias páginas. Este complemento solo necesita cargarse cuando se utiliza esta vista y no quiero tener que saber qué plugins está usando cada vista parcial ...
Gracias por tus respuestas.
Esto parece una pregunta similar (aunque no del todo). ¿Es una mala práctica devolver vistas parciales que contengan javascript?
Hoy he creado mi propia solución que se ajusta a la perfección. Si es un buen diseño o no, es para que todos decidan, ¡pero pensé que debería compartirlo de cualquier manera!
Debajo está mi clase HtmlExtensions que te permite hacer esto en tu página maestra:
<%=Html.RenderJScripts() %>
Mi clase 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
}
Que esta pasando?
La clase anterior extenderá el HtmlHelper con métodos para agregar enlaces de JavaScript a una colección que está siendo almacenada por la colección HtmlHelper.ViewContext.TempData
. Al final de la página maestra pongo <%=Html.RenderJScripts() %>
que hará un bucle en la colección jscripts dentro de HtmlHelper.ViewContext.TempData
y los renderizará en la salida.
Sin embargo, hay un inconveniente ... Debe asegurarse de no renderizar los scripts antes de agregarlos. Si desea hacer esto para los enlaces css, por ejemplo, no funcionaría porque debe colocarlos en la etiqueta <head>
de su página y htmlhelper mostraría el resultado antes de que haya agregado un enlace.
La razón por la que colocarías un script en la parte inferior de la página es para asegurarte de que el dom se haya cargado antes de intentar cualquier manipulación. Esto también se puede lograr en algo como $ (document) .ready (callback); método jQuery.
Comparto la idea de no incluir JavaScript incrustado en el html. En su lugar, utilizo un helper Html para crear un div vacío para usar como una instrucción de servidor. El helper sig es Html.ServerData (String name, Object data);
Uso este método ServerData para obtener instrucciones del servidor al cliente. La etiqueta div lo mantiene limpio y el atributo "data-" es válido html5.
Para la instrucción loadScript puedo hacer algo como esto en mi ascx o aspx:
<%= Html.ServerData("loadScript", new { url: "pathTo.js" }) %>
O agregue otro ayudante para hacer esto que se vea un poco más limpio:
<%= Html.LoadScript("~/path/to.js") %>
La salida html sería:
<div name="loadScript" data-server="encoded json string">
Luego tengo un método jQuery que puede encontrar cualquier etiqueta de datos del servidor: $ (containingElement) .serverData ("loadScript"); // devuelve una jQuery como matriz de los objetos json descodificados.
El cliente puede verse más o menos así:
var script = $(containingelement").serverData("loadScript"); $.getScript(script.url, function () { // script has been loaded - can do stuff with it now });
Esta técnica es ideal para controles de usuario o scripts que deben cargarse dentro de un contenido cargado de javascript. La versión que escribí está un poco más involucrada en el manejo de scripts de caché, por lo que solo se cargan una vez por carga de página completa y contienen callbacks y jQuery triggers para que pueda engancharlos cuando esté listo.
Si alguien está interesado en la versión completa de esto (desde la extensión MVC a jQuery) me gustaría mostrar esta técnica con más detalle. De lo contrario, espera que le brinde a alguien una nueva forma de abordar este complicado problema.
Los diseñadores de MVC tuvieron muchos problemas para evitar el uso de código subyacente, pero al crear un archivo llamado <viewname> .aspx.cs y modificar el atributo inherits de la página aspx en consecuencia, aún es posible obtenerlos .
Yo diría que el mejor lugar para poner el include sería en el controlador Page_Load en el código subyacente (usando Page.ClientScript.RegisterClientScriptInclude).
Mi preferencia será crear una página plugin.master que herede de su Site.master principal. La idea es que rellene estos complementos en plugin.master y que las 8 páginas que usarán esta vista parcial hereden de plugin.master.
Parece muy similar a esta pregunta: vincular bibliotecas de JavaScript en controles de usuario
Voy a volver a publicar mi respuesta que esa pregunta aquí.
Definitivamente recomendaría no ponerlos en parciales por exactamente la razón que mencionas. Existe una alta probabilidad de que una vista pueda obtener dos parciales que tengan referencias al mismo archivo js. También tienes el rendimiento de carga de js antes de cargar el resto del html.
No conozco las mejores prácticas, pero elijo incluir cualquier archivo js común dentro de la página maestra y luego definir un ContentPlaceHolder por separado para algunos archivos js adicionales que son específicos para un número particular o pequeño de vistas.
Aquí hay una página maestra de ejemplo: es bastante explicativa.
<%@ 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 son obviamente mis propias extensiones, pero una vez más, se explican por sí mismas en lo que hacen.
Entonces, por ejemplo, en una vista SignUp.aspx, tendría
<asp:Content ID="signUpContent" ContentPlaceHolderID="AdditionalJS" runat="server">
<%= Html.JSBlock("/scripts/pages/account.signup.js", "/scripts/pages/account.signup.min.js") %>
</asp:Content>
HTHs, Charles
PD. Aquí hay una pregunta de seguimiento que hice para minificar y concatenar archivos js: Concatenar y minificar JS sobre la marcha O en tiempo de compilación - ASP.NET MVC
EDITAR: Como solicité en mi otra respuesta, mi implementación de .JSBlock (a, b) como se solicitó
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);
}
Y luego, donde sucede la magia ...
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);
}
hejdig.
Jugando con Aspnetmvc3 decidí, por ahora, simplemente incluir mi archivo javascript en el parcial
<script src = "@ Url.Content (" ~ / Scripts / User / List.js ")" type = "text / javascript"> </ script>
Este archivo js es específico para mi archivo /user/List.schtml.
/DE