Node.js с Express: импорт клиентского javascript с использованием тегов script в представлениях Jade? - PullRequest
19 голосов
/ 09 апреля 2011

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

Ответы [ 6 ]

39 голосов
/ 11 апреля 2011

Вы можете иметь их в макете и указать, какие библиотеки загружать на «контроллеры».

// 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']
  }
}
20 голосов
/ 09 апреля 2011

Я сделал то же самое, используя решение из этой темы:

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

Чем у вас может быть помощник, который выводит теги скрипта в начало макета

renderScriptTags () Код помощника:

app.helpers({ renderScriptTags: function(scripts) {
  return scripts.map(function(script) {
    return '<script src="scripts/' + script + '"></script>';
  }).join('\n ');

В шаблоне макета в разделе head у вас будет:

- renderScriptTags(scripts)

Теперь, чтобы добавить скрипт в тег head, вам просто нужно вставить скрипт в переменную «scripts» в вашем шаблоне содержимого Jade (шаблон тела):

- scripts.push('myscript.js'); 

Таким образом, страница отобразит jquery.js и myscript.js в верхнюю часть страницы

UPDATE

Кажется, что новейшая экспресс-версия обрабатывает местных жителей по-другому, для правильной работы вы можете сделать это (хотя я не уверен, что это оптимальное решение, мне нужно немного покопаться в этом)

Вы можете использовать renderScriptTags () помощника предыдущего метода в шаблоне макета, как и раньше.

Но не устанавливайте переменные scripts в локальные переменные, вместо этого создайте динамический помощник, который сделает переменную scripts доступной в наших шаблонах:

app.dynamicHelpers({
  scripts: function(req, res){
    return ['jquery.js']; //this will be available in all views
  }
});

А затем, чтобы добавить конкретный скрипт из шаблона вашего тела (точно так же, как и раньше):

- scripts.push('myscript.js'); 

Теперь для этого конкретного вида вы должны правильно отобразить jquery.js и myscript.js

8 голосов
/ 17 января 2013

Можно сделать это Правильно (tm) в последней версии Jade (0.28.1), сохранив все это внутри шаблонов / представлений, не взламывая содержимое страницы (ссылки на скрипты) в другом месте:

  • Объявите заголовок как именованный блок в вашем шаблоне:
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
2 голосов
/ 28 ноября 2011

Вот альтернативный способ сделать это (используя ответ 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;
2 голосов
/ 17 апреля 2011

Я предполагаю, что проблема (после краткого прочтения) состоит в том, что вы не «очищаете» массив, устанавливая его .length в 0, чтобы удалить старые значения, поэтому каждый запрос может просто выдвигать все больше и больше строк

1 голос
/ 04 апреля 2014

Я не уверен, какой смысл подходов до сих пор. Для меня гораздо чище сделать следующее ...

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

...