带Express的Node.js:在Jade视图中使用脚本标记导入客户端javascript?
我有一个node.js express服务器,运行着Jade模板引擎 我有一个布局jade文件,它导入了各个视图的主体,如下所示:带Express的Node.js:在Jade视图中使用脚本标记导入客户端javascript?,javascript,node.js,express,pug,Javascript,Node.js,Express,Pug,我有一个node.js express服务器,运行着Jade模板引擎 我有一个布局jade文件,它导入了各个视图的主体,如下所示: !!! html head title= title || 'Title not set.' body #header h1 Header. #content!= body //- this renders the body of an individual view
!!!
html
head
title= title || 'Title not set.'
body
#header
h1 Header.
#content!= body //- this renders the body of an individual view
#footer
p Footer.
例如,以下索引页:
p Welcome to the front page.
p This page serves as a now.js test.
这个很好用。但是,我现在想为这个索引页面专门包含两个客户端javascript库(因此不是每个页面,这就是为什么我不能把它放在布局的开头)
这项工作:
//- 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.
但是,这会将脚本加载到完整页面的主体中,这不是有效的HTML,对吗
据我所知,如果我想正确地执行,脚本应该加载到head中,但是head部分由布局文件处理
那么,我如何正确地包含这些专门用于特定视图/页面的客户端javascript库呢?我已经使用此线程中的解决方案完成了同样的工作: 您可以在视图选项中声明“scripts”变量: app.js:
app.set('view options', { locals: { scripts: ['jquery.js'] } }); // You can declare the scripts that you will need to render in EVERY page
app.dynamicHelpers({
scripts: function() {
//scripts to load on every page
return ['js/jquery.min.js','js/jquery-ui.min.js','js/all.js'];
}
});
这样,就可以有一个助手将脚本标记渲染到布局的头部
renderScriptTags()帮助程序代码:
app.helpers({ renderScriptTags: function(scripts) {
return scripts.map(function(script) {
return '<script src="scripts/' + script + '"></script>';
}).join('\n ');
现在,要在head标签上添加脚本,只需将脚本推入jade内容模板(body模板)上的“scripts”变量:
这样,页面将把jquery.js和myscript.js呈现到页面的头部
更新
似乎最新的express版本以不同的方式处理本地人,要使其正常工作,您可以这样做(但我不确定这是否是最佳解决方案,我需要对此进行一点挖掘)
您可以像以前一样在布局模板中使用上一个方法的renderScriptTags()辅助对象
但不要将脚本变量设置为局部变量,而是创建一个动态帮助器,使脚本变量在我们的模板中可用:
app.dynamicHelpers({
scripts: function(req, res){
return ['jquery.js']; //this will be available in all views
}
});
然后,要添加特定脚本,请从您的主体模板(与前面完全相同):
现在,对于这个特定视图,应该正确呈现jquery.js和myscript.js您可以在布局上放置它们,并指定要在“控制器”上加载哪些库 以及您的“控制器”:
我假设问题(简单阅读本文)在于您没有“刷新”数组,而是将其.length设置为0以删除旧值,因此每个请求可能只是推送越来越多的字符串,这里有一种替代方法(使用ShadowCloud的答案)。通过泛化一点,您可以指定本地和远程脚本,然后将它们延迟到页面加载之后: app.js:
app.set('view options', { locals: { scripts: ['jquery.js'] } }); // You can declare the scripts that you will need to render in EVERY page
app.dynamicHelpers({
scripts: function() {
//scripts to load on every page
return ['js/jquery.min.js','js/jquery-ui.min.js','js/all.js'];
}
});
然后,您可以在视图中的任何位置添加本地或远程脚本
//- 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')
jade:(我把它放在身体的末端,首先装载可见的东西,但它真的可以去任何地方)
在最新的Jade(0.28.1)中,通过将所有内容保存在模板/视图中,而不在其他地方对页面内容(脚本链接)进行黑客攻击,可以以正确的方式(tm)完成此操作:
- 在模板中将头部声明为命名块:
- 在视图中附加特定于页面的标题元素(包括脚本标记):
我不确定到目前为止这些方法的意义是什么。对我来说,做以下事情要干净得多 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
doctype html
html
头
头衔
块头脚本//需要在中的脚本的占位符
链接(rel='stylesheet',href='/styles/style.css')
块样式//样式的占位符
身体
块内容
脚本(src='/libs/jquery/dist/jquery.min.js')//这将在每个页面中的所有脚本之前呈现
阻止脚本//正文中脚本的占位符
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')
扩展布局
块样式//这将在
链接(rel='stylesheet',href='/styles/films.css')
链接(rel='stylesheet',href='/styles/pagination.css')
块头脚本//这也将在
脚本(src='/js/somescript.js')
块内容
h1=标题
什么别的
块脚本//这将在正文末尾渲染
脚本(src='/js/libs/someotherscript.js')
scirpt(src='/libs/doT/doT.js')
这样,无论在
.jade
页面的何处放置块,它们都将始终呈现在正确的位置。您只需将它们添加到常规脚本列表中,然后将这些脚本添加到常规布局文件的头部。但是,我需要为特定视图设置特定脚本。您可以通过将视图特定脚本推入脚本变量,将其设置到视图中,以便在布局标头中呈现,这不正是您试图实现的吗?@ShadowCloud,我不确定,您将脚本推到哪里?这是否会导致脚本在其他视图中加载,以及脚本变量似乎在主作用域中声明?@Tom:我注意到,在较新版本的express中,局部变量的处理方式有所不同,我在更新的答案中为您提供了一个修改后的解决方案(可能有更好的解决方案,但它应该可以工作)@ShadowCloud在哪里调用script.push?在特定视图中?我想这会更好,因为脚本不应该在视图中设置,而应该在控制器中设置。我更喜欢在控制器上设置脚本,这样您就可以轻松地重用代码。您是怎么做的
//- 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')
//- 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;
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
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
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
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')