21

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 ではありませんよね?

私の知る限り、スクリプトは適切に実行したい場合は head にロードする必要がありますが、head セクションはレイアウト ファイルによって処理されます。

では、これらのクライアント側の JavaScript ライブラリを特定のビュー/ページ専用に適切に含めるにはどうすればよいでしょうか?

4

6 に答える 6

40

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

// 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']
  }
}
于 2011-04-10T23:07:53.567 に答える
20

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

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

head セクションのレイアウト テンプレートには、次のものがあります。

- renderScriptTags(scripts)

head タグにスクリプトを追加するには、スクリプトを jade コンテンツ テンプレート (body テンプレート) の "scripts" 変数にプッシュするだけです。

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

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

アップデート

最新の高速バージョンでは、ローカルを別の方法で処理しているようです。これを適切に機能させるには、これを行うことができます (最適な解決策であるかどうかはわかりませんが、これを少し掘り下げる必要があります)。

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

ただし、スクリプト変数をローカルに設定しないでください。代わりに、スクリプト変数をテンプレートで使用できるようにする動的ヘルパーを作成します。

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

次に、body テンプレートから特定のスクリプトを追加するには (前とまったく同じ):

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

さて、この特定のビューでは、jquery.js と myscript.js を適切にレンダリングする必要があります。

于 2011-04-09T13:54:15.693 に答える
8

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

  • テンプレートで頭を名前付きブロックとして宣言します。
Doctype 5
html
  頭
    //名前付きブロックを使用すると、各ページにカスタムヘッドエントリを追加できます
    ブロックヘッド
        title=タイトル
        link(rel ='stylesheet'、href ='/ css / style.css')
        script(type = "text / javascript"、src = "/ js / some-default-script.js")
  体
    コンテンツをブロックする
  • ビューにページ固有のヘッド要素(スクリプトタグを含む)を追加します。
レイアウトを拡張します

//ここでは、テンプレートヘッドを参照し、それに追加します
ブロック追加ヘッド
    meta(name = "something"、content = "blah")
    link(href = "/ css / another.css"、rel = "stylesheet"、type = "text / css")
    スタイル
        div.foo {
            位置:絶対;
        }
    script(src = "/ js / page-specific-script.js")

コンテンツをブロックする
    #page-contents-follows
于 2013-01-17T10:45:34.667 に答える
2

これを行う別の方法を次に示します(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;
于 2011-11-27T22:24:40.460 に答える
2

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

于 2011-04-17T18:59:27.537 に答える
1

これまでのアプローチのポイントが何であるかはわかりません。私にとっては、次のことを行う方がはるかにクリーンです...

レイアウト.ジェイド:

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配置しても問題なく、常に正しい場所にレンダリングされます。

于 2014-04-04T18:02:39.683 に答える