javascript - servidor - que es express js
Node.js con Express: ¿Importando javascript del lado del cliente usando etiquetas de script en vistas de Jade? (6)
Aquí hay una forma alternativa de hacerlo (usando la respuesta de ShadowCloud). Al generalizar un poco, puede especificar los scripts locales y remotos, y luego diferirlos hasta después de la carga de la página:
app.js:
app.dynamicHelpers({
scripts: function() {
//scripts to load on every page
return [''js/jquery.min.js'',''js/jquery-ui.min.js'',''js/all.js''];
}
});
luego, puede agregar scripts locales o remotos en cualquier punto dentro de una vista
//- local script
- scripts.push(''js/myPage.js'');
//- remote script ( note: this is a schemeless url. You can use http(s)? ones too )
- scripts.push(''//platform.twitter.com/widgets.js'')
layout.jade: (Lo puse al final del cuerpo para cargar las cosas visibles primero, pero puede ir a cualquier parte realmente)
//- Bring the scripts into a client-side array,
//- and attach them to the DOM one by one on page load
script
var page_scripts = !{''["'' + scripts.join(''","'') + ''"]''};
function loadJS() {
for(var i in page_scripts) {
var e = document.createElement("script");
e.src = page_scripts[i];
document.body.appendChild(e);
}
}
// Check for browser support of event handling capability
if (window.addEventListener)
window.addEventListener("load", loadJS, false);
else if (window.attachEvent)
window.attachEvent("onload", loadJS);
else window.onload = loadJS;
Tengo un servidor node.js Express que se ejecuta con el motor de plantillas de Jade.
Tengo un archivo de jade de diseño que importa el cuerpo de las vistas individuales así:
!!!
html
head
title= title || ''Title not set.''
body
#header
h1 Header.
#content!= body //- this renders the body of an individual view
#footer
p Footer.
Por ejemplo, la siguiente página de índice:
p Welcome to the front page.
p This page serves as a now.js test.
Esto funciona bien. Sin embargo, ahora quiero incluir dos bibliotecas de javascript del lado del cliente específicamente para esta página de índice (y, por lo tanto, no todas las páginas, por lo que no puedo ponerlo en la cabecera del diseño).
Esto funciona:
//- import jquery
script(type=''text/javascript'', src=''./jquery-1.5.2.min.js'');
//- import now.js (hosts itself)
script(type=''text/javascript'', src=''/nowjs/now.js'')
//- import the chat client
script(type=''text/javascript'', src=''./indexChatClient.js'')
p Welcome to the front page.
p This page serves as a now.js test.
Sin embargo, esto carga los scripts en el cuerpo de la página completa, que no es un HTML válido, ¿verdad?
Por lo que sé, los scripts deben cargarse en la cabeza si quiero hacerlo correctamente, pero la sección de la cabeza es manejada por el archivo de diseño.
Entonces, ¿cómo incluiría adecuadamente estas bibliotecas de javascript del lado del cliente específicamente para una determinada vista / página?
Es posible hacerlo de la manera correcta (tm) en el último Jade (0.28.1) guardándolo todo dentro de las plantillas / vistas, sin piratear el contenido de la página (enlaces de guiones) en otra parte:
- Declara la cabeza como un bloque con nombre en tu plantilla:
doctype 5 html head // named block allows us to append custom head entries in each page block head title= title link( rel=''stylesheet'', href=''/css/style.css'' ) script( type="text/javascript", src="/js/some-default-script.js" ) body block content
- Agregue los elementos de encabezado específicos de su página (incluidas las etiquetas de script) en sus vistas:
extends layout // here we reference the template head and append to it block append head meta( name="something", content="blah" ) link( href="/css/another.css", rel="stylesheet", type="text/css" ) style div.foo { position: absolute; } script( src="/js/page-specific-script.js" ) block content #page-contents-follows
He hecho lo mismo usando la solución de este hilo:
http://groups.google.com/group/express-js/browse_thread/thread/8c2006dc7bab37b1/f9a273c836e0a2ac
Puede declarar una variable de "scripts" en las opciones de visualización:
app.js:
app.set(''view options'', { locals: { scripts: [''jquery.js''] } }); // You can declare the scripts that you will need to render in EVERY page
De lo que puede tener un ayudante que represente las etiquetas de script en el encabezado del diseño
Código de ayuda de renderScriptTags ():
app.helpers({ renderScriptTags: function(scripts) {
return scripts.map(function(script) {
return ''<script src="scripts/'' + script + ''"></script>'';
}).join(''/n '');
En la plantilla de diseño en la sección de cabecera tendrá:
- renderScriptTags(scripts)
Ahora, para agregar una secuencia de comandos en la etiqueta de la cabeza, solo deberá insertar la secuencia de comandos en la variable "secuencias de comandos" en su plantilla de contenido de jade (plantilla de cuerpo):
- scripts.push(''myscript.js'');
De esta manera, la página mostrará jquery.js y myscript.js en el encabezado de la página.
ACTUALIZAR
Parece que la versión Express más nueva maneja a los locales de una manera diferente, para que esto funcione correctamente, puedes hacerlo (aunque no estoy seguro de que sea la solución óptima, tendría que profundizar un poco en esto)
Puede usar el helper renderScriptTags () del método anterior en su plantilla de diseño como antes.
Pero no establezca las variables de scripts en locales, en su lugar, cree un ayudante dinámico que haga que una variable de scripts esté disponible en nuestras plantillas:
app.dynamicHelpers({
scripts: function(req, res){
return [''jquery.js'']; //this will be available in all views
}
});
Y luego, para agregar un script específico, desde su plantilla de cuerpo (exactamente como antes):
- scripts.push(''myscript.js'');
Ahora, para esta vista específica, debes tener jquery.js y myscript.js representados correctamente
No estoy seguro de cuál es el punto de los enfoques hasta ahora. Para mí es mucho más limpio hacer lo siguiente ...
layout.jade:
doctype html
html
head
title= title
block headscripts // placeholder for scripts that need to be in the <head>
link(rel=''stylesheet'', href=''/styles/style.css'')
block styles // placeholder for styles
body
block content
script(src=''/libs/jquery/dist/jquery.min.js'') // this will render before all scripts in every page
block scripts // placeholder for scripts that go in the body
somepage.jade:
extends layout
block styles // this will render in the <head>
link(rel=''stylesheet'', href=''/styles/films.css'')
link(rel=''stylesheet'', href=''/styles/pagination.css'')
block headscripts // this will also render in the <head>
script(src=''/js/somescript.js'')
block content
h1= title
div.someotherstuff
block scripts // this will render at the end of the body
script(src=''/js/libs/someotherscript.js'')
scirpt(src=''/libs/doT/doT.js'')
De esta manera, no importa en .jade
páginas .jade
coloques tus bloques, siempre se renderizarán en los lugares correctos.
Puede tenerlos en el diseño y especificar qué bibliotecas cargar en los "controladores".
// layout.jade
!!!
html
head
title= title || ''Title not set.''
-each script in scripts
script(type=''text/javascript'', src= script)
body
#header
h1 Header.
#content!= body //- this renders the body of an individual view
#footer
p Footer.
Y tu "controlador":
// app.js
app.get(''/'', function (req, res) {
res.render({
scripts: [''jquery.min.js'', ''/nowjs/now.js'']
}
}
Supongo que el problema (al leer esto brevemente) es que no está "vaciando" la matriz, estableciendo su longitud en 0 para eliminar los valores antiguos, por lo que cada solicitud podría estar presionando más y más cadenas