Node.js с Express: импорт javascript на стороне клиента с использованием тегов script в представлениях Jade?
У меня есть экспресс-сервер node.js, работающий с движком шаблонов Jade.
У меня есть jade файл макета, который импортирует тело отдельных представлений так:
!!!
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, правильно?
Насколько я знаю, скрипты должны быть загружены в голову, если я хочу сделать это правильно, но раздел главы обрабатывается файлом макета.
Итак, как я должен правильно включать эти клиентские библиотеки javascript специально для определенного вида/страницы?
Ответы
Ответ 1
Я сделал то же самое, используя решение из этого потока:
http://groups.google.com/group/express-js/browse_thread/thread/8c2006dc7bab37b1/f9a273c836e0a2ac
Вы можете объявить переменную "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
Чем у вас может быть помощник, который отображает теги script в голову макета
renderScriptTags() Код помощника:
app.helpers({ renderScriptTags: function(scripts) {
return scripts.map(function(script) {
return '<script src="scripts/' + script + '"></script>';
}).join('\n ');
В шаблон макета в разделе главы вы будете:
- renderScriptTags(scripts)
Теперь, чтобы добавить script в тег head, вам просто нужно нажать script в переменную "scripts" в вашем шаблоне контента jade (шаблон тела):
- scripts.push('myscript.js');
Таким образом, страница будет отображать jquery.js и myscript.js в начало страницы
UPDATE
Кажется, что новейшая экспресс-версия управляет местными жителями по-другому, чтобы сделать эту работу должным образом, вы можете это сделать (я не уверен, что это оптимальное решение, хотя мне нужно немного это выкопать)
Вы можете использовать помощник renderScriptTags() предыдущего метода в шаблоне макета, как и раньше.
Но не устанавливайте переменные сценариев в локальные, вместо этого создайте динамический помощник, который сделает переменную скриптов доступной в наших шаблонах:
app.dynamicHelpers({
scripts: function(req, res){
return ['jquery.js']; //this will be available in all views
}
});
И затем, чтобы добавить конкретный script из вашего шаблона тела (как и раньше):
- scripts.push('myscript.js');
Теперь для этого конкретного представления вы должны правильно отобразить jquery.js и myscript.js
Ответ 2
Их можно разместить на макете и указать, какие библиотеки загружать на "контроллерах".
// 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.
И ваш "контроллер":
// app.js
app.get('/', function (req, res) {
res.render({
scripts: ['jquery.min.js', '/nowjs/now.js']
}
}
Ответ 3
Это возможно сделать в правильном направлении (tm) в последней версии Jade (0.28.1), сохранив ее внутри шаблонов/представлений, без взлома содержимого страницы (script) в другом месте:
- Объявите головку как именованный блок в шаблоне:
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
- Добавляйте свои элементы заголовка страницы (включая теги script) в свои представления:
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
Ответ 4
Я предполагаю, что проблема (из краткого ознакомления с этим) заключается в том, что вы не "промываете" массив, установив его .length в 0 для удаления старых значений, поэтому каждый запрос может просто нажимать все больше строк
Ответ 5
Вот альтернативный способ сделать это (используя ответ ShadowCloud). Обобщая бит, вы можете указать как локальные, так и удаленные сценарии, а затем отложить их до загрузки страницы:
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'];
}
});
то вы можете добавить локальные или удаленные скрипты в любой точке внутри представления
//- 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: (Я положил его в конец тела, чтобы сначала загрузить видимые вещи, но он может пойти куда угодно)
//- 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;
Ответ 6
Я не уверен, какова точка подхода до сих пор. Мне гораздо проще сделать следующее...
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')
Таким образом, не имеет значения, где на ваших страницах .jade
вы помещаете свои блоки, они всегда будут отображаться в правильных местах.