Подтвердить что ты не робот

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 специально для определенного вида/страницы?

4b9b3361

Ответ 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 вы помещаете свои блоки, они всегда будут отображаться в правильных местах.