web-dev-qa-db-ja.com

Node.js with Express:Jadeビューでスクリプトタグを使用してクライアント側のJavaScriptをインポートしますか?

Jadeテンプレートエンジンで実行されているnode.jsエクスプレスサーバーを持っています。

次のように、個々のビューの本体をインポートするレイアウト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.

これは正常に動作します。ただし、このインデックスページ専用に2つのクライアント側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ライブラリを適切に含めるにはどうすればよいでしょうか。

20
Tom

私はこのスレッドのソリューションを使用して同じことを行いました:

http://groups.google.com/group/express-js/browse_thread/thread/8c2006dc7bab37b1/f9a273c836e0a2ac

「スクリプト」変数をビューオプションに宣言できます。

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 ');

ヘッドセクションのレイアウトテンプレートには、次のものが含まれます。

- renderScriptTags(scripts)

次に、headタグにスクリプトを追加するには、翡翠コンテンツテンプレート(ボディテンプレート)の「scripts」変数にスクリプトをプッシュする必要があります。

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

このようにして、ページはjquery.jsとmyscript.jsをページの先頭にレンダリングします

[〜#〜]更新[〜#〜]

最新の高速バージョンはローカルを別の方法で処理するようです、これを適切に機能させるには、これを行うことができます(ただし、これが最適なソリューションであるかどうかはわかりませんが、これを少し掘る必要があります)

以前と同じように、レイアウトテンプレートで前のメソッドのrenderScriptTags()ヘルパーを使用できます。

ただし、スクリプト変数をローカルに設定しないでください。代わりに、テンプレートで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を適切にレンダリングする必要があります

20
BFil

それらをレイアウトに配置し、「コントローラー」にロードするライブラリーを指定できます。

// 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']
  }
}
39
masylum

最新のJade(0.28.1)では、他の場所でページコンテンツ(スクリプトリンク)をハッキングすることなく、テンプレート/ビュー内にすべてを保持することで、正しい方法(tm)を実行できます。

  • テンプレートで、ヘッドを名前付きブロックとして宣言します。
 doctype 5 
 html 
 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 
 
 //ここでは、テンプレートヘッドを参照して追加します
 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")
 
ブロックコンテンツ
#page-contents-follows 
8
Gilead

これを行う別の方法を次に示します(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
jhoff

(これを簡単に読んでから)問題は、配列を「フラッシュ」せずに.lengthを0に設定して古い値を削除することではないため、各リクエストがますます多くの文字列をプッシュする可能性があると思います

2
tjholowaychuk

これまでの取り組みのポイントは何なのかわかりません。私にとっては、次のことを行う方がはるかにきれいです...

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ページのどこにブロックを配置しても問題ありません。常に正しい場所にレンダリングされます。

1
Stephen Collins