2013-05-08 23 views
59

私はJekyllを使ってブログを構築しました。すべてのテンプレート/レイアウトでアクセス可能なファイル_config.ymlに変数を定義することができます。私は現在Node.JS/ExpressEJSテンプレートとejs-locals(部分/レイアウト用)を使用しています。site.titleのようなグローバル変数に類似したものを探していますが、これはにあります。 、ここで Express/Node.JSを使用して、すべてのビューでアクセス可能なグローバル変数を作成する方法は?

は:

exports.index = function(req, res){ 
    res.render('index', { 
     siteTitle: 'My Website Title', 
     pageTitle: 'The Root Splash Page', 
     author: 'Cory Gross', 
     description: 'My app description', 
     indexSpecificData: someData 
    }); 
}; 

exports.home = function (req, res) { 
    res.render('home', { 
     siteTitle: 'My Website Title', 
     pageTitle: 'The Home Page', 
     author: 'Cory Gross', 
     description: 'My app description', 
     homeSpecificData: someOtherData 
    }); 
}; 

私が望む私が現在やっているの一例である私のすべてのページに同じまま、著者/会社名、(むしろ、ページのタイトルより)。へ私のサイトのタイトル、説明、著者などのような変数を1か所に定義して、それらにアクセスできるようにする私のレイアウト/テンプレートでEJSを使用して、res.renderの各呼び出しにオプションとして渡す必要はありません。これを行う方法はありますか、それでも私は各ページに固有の他の変数を渡すことができますか?

答えて

80

Express 3 API Referenceをもう少し勉強する機会を得た後、私が探していたことを発見しました。具体的には、app.localsのエントリと、それより少し下のビットres.localsが必要な回答を保持していました。

私は自分自身で、関数app.localsがオブジェクトをとり、すべてのプロパティをアプリケーションにスコープされたグローバル変数として格納していることを発見しました。これらのグローバルは、ローカル変数として各ビューに渡されます。ただし、関数res.localsは要求にスコープが設定されているため、応答ローカル変数はその特定の要求/応答中にレンダリングされたビューに対してのみアクセス可能です。私が追加されたなかったものを、私のapp.jsで私の場合のためにそう

:次に

app.locals({ 
    site: { 
     title: 'ExpressBootstrapEJS', 
     description: 'A boilerplate for a simple web application with a Node.JS and Express backend, with an EJS template with using Twitter Bootstrap.' 
    }, 
    author: { 
     name: 'Cory Gross', 
     contact: '[email protected]' 
    } 
}); 

これらの変数の全てはsite.titlesite.descriptionauthor.nameauthor.contactとしての私の見解でアクセス可能です。

また、res.localsというリクエストに対する各応答のローカル変数を定義することもできますし、render呼び出しのoptionsパラメータとしてページのタイトルのような変数を渡すこともできます。

このメソッドはではありません。あなたのミドルウェアでこれらのローカルを使用することができます。 Pickelsが次のようなコメントで示唆しているように、私は実際にこの問題にぶつかりました。この場合、代替(および評価)の回答でミドルウェア機能を作成する必要があります。あなたのミドルウェア機能は、応答ごとにres.localsにそれらを追加し、次にnextを呼び出す必要があります。このミドルウェア機能は、これらのローカルを使用する必要のある他のミドルウェアの上に配置する必要があります。

EDIT:app.localsres.locals経由宣言し、地元の人々との間にもう一つの違いは、app.localsと変数は、単一の時間を設定され、アプリケーションの生涯にわたって持続していることです。あなたのミドルウェアにres.localsの地方を設定すると、リクエストを受け取るたびに設定されます。基本的に、app.localsでグローバルを設定することをお勧めします。値が変更されない場合は、app.localsに1回だけ設定する方が効率的です。あなたは今、この

global.myvar = 100; 

のようなものを追加する必要がありますあなたのapp.jsで

+1

app.localsは、私が提案したものよりも意味があります。それは1つのキャッチを持っていますが、ミドルウェアのローカルにアクセスすることはできません。この場合、おそらく問題ではありませんが、時にはあなたが陥ってしまうようなものです。 – Pickels

+0

ブエノ!わかりやすいドキュメントを明確にしてくれてありがとう! –

+0

また、jsファイルやjsonファイルで構成を定義し、必要なときにそのファイルを必要()にすることもできます。ファイルはアプリケーション中で一度だけロードされ、必要なすべてのモジュールは定義した値にアクセスします。 http://stackoverflow.com/questions/5869216/how-to-store-node-js-deployment-settings-configuration-files –

41

一般的なミドルウェアのlocalsオブジェクトに追加することで、これを行うことができます。

app.use(function (req, res, next) { 
    res.locals = { 
    siteTitle: "My Website's Title", 
    pageTitle: "The Home Page", 
    author: "Cory Gross", 
    description: "My app's description", 
    }; 
    next(); 
}); 

ローカルは、ローカルオブジェクトを上書きするのではなく、そのオブジェクトを拡張する関数です。したがって、次の作品にも

res.locals({ 
    siteTitle: "My Website's Title", 
    pageTitle: "The Home Page", 
    author: "Cory Gross", 
    description: "My app's description", 
}); 

全例

var app = express(); 

var middleware = { 

    render: function (view) { 
     return function (req, res, next) { 
      res.render(view); 
     } 
    }, 

    globalLocals: function (req, res, next) { 
     res.locals({ 
      siteTitle: "My Website's Title", 
      pageTitle: "The Root Splash Page", 
      author: "Cory Gross", 
      description: "My app's description", 
     }); 
     next(); 
    }, 

    index: function (req, res, next) { 
     res.locals({ 
      indexSpecificData: someData 
     }); 
     next(); 
    } 

}; 


app.use(middleware.globalLocals); 
app.get('/', middleware.index, middleware.render('home')); 
app.get('/products', middleware.products, middleware.render('products')); 

私はまた、一般的なレンダリングミドルウェアを追加しました。こうすることで、res.renderを各ルートに追加する必要がなくなり、コードの再利用が向上します。再利用可能なミドルウェアのルートを通過すると、開発のスピードを大幅に向上させるビルディングブロックがたくさんあることに気付くでしょう。

+0

私はこれが古い答えですけど、 'req'と' res'のためのあなたの 'globalLocals'機能でのparamsが後方にあります。 – brandon927

+0

グローバルになるように意図されたデータをクエリすることはできますか?各ページリクエストからdbから直接ロードされるnavbarデータ?これは地元住民の使用量を上回る可能性があると思われます。マングースコール。私はnavbarがグローバルであるので、すべてのルートで直接ロードを探しています。後でキャッシングを調べます。代わりに、たぶん私は一度実行される関数を必要とし、次にデータを収集した後にこれらをローカルにロードします。 – blamb

6

は、この変数を使用したいすべてのファイルで、あなただけの私が見つけエクスプレス4.0の場合myvar

+0

私はrequireモジュールを使用していて、どこでも 'global.myvar'として参照しなければなりませんでした。これはsocket.ioの素敵な簡単な解決策でした。ハンドラから他のファイルのメッセージを出したいと思っています。私は自分の "io"オブジェクトを 'global.myIO'に入れて、すべてがうまくいっています。 –

+3

これは実際にはノードの開発では推奨されていないか、または良い方法と見なされていません。 Node.JSには、CommonJSシステムに基づくモジュールシステムの実装が含まれており、requireメソッドを使用する代わりに、グローバルスコープを共有しないモジュールのアイデアを完全に柱としています。これは、質問のようなエクスプレスビュー/テンプレート用のローカルではなく、ノード内のグローバルjs varも設定します。 –

+0

@CoryGross要求オブジェクトをこのようなグローバル変数として設定するのは良い方法ですか? –

9

としてそれにアクセスすることができますアプリケーションレベルの変数を使用することは少し違って動作します&コーリーの答えは私のためには機能しませんでした。ドキュメントから

http://expressjs.com/en/api.html#app.locals

私は例えば

app.locals.baseUrl = "http://www.google.com" 

あなたは

app.locals 

でのアプリのためのグローバル変数を宣言することができることを発見し、その後、あなたのアプリケーションでは、これらにアクセスすることができますエクスプレスミドルウェアの変数&にアクセスするには、reqオブジェクトで

req.app.locals.baseUrl 

var app = express(); 
app.locals.appName = "DRC on FHIR"; 

を次を経由して設定しapp.js

にそのアプリのためapp.locals変数を更新することにより、これを行うに

console.log(req.app.locals.baseUrl) 
//prints out http://www.google.com 
+0

また、コードで新しい地方自治体が追加されると、エクスプレスサーバを再起動する必要があります。 – Wtower

1

一つの方法/アクセス

スクリーンショットとエラボレーション
app.listen(3000, function() { 
    console.log('[' + app.locals.appName + '] => app listening on port 3001!'); 
}); 

を取得@RamRoviの例から若干強化されています。

enter image description here

1

あなたはまた、 "グローバル" を使用することができ

例:

は次のように宣言します。このような

app.use(function(req,res,next){ 
     global.site_url = req.headers.host; // hostname = 'localhost:8080' 
     next(); 
    }); 

使用:任意のビューまたはEJSで は <ファイル% console.log(site_url); %>

(jsファイル内) console.log(site_url);

1

汚染されたグローバルスコープを避けるために私が行うことは、どこにでも含めることができるスクリプトを作成することです。

// my-script.js 
const ActionsOverTime = require('@bigteam/node-aot').ActionsOverTime; 
const config = require('../../config/config').actionsOverTime; 
let aotInstance; 

(function() { 
    if (!aotInstance) { 
    console.log('Create new aot instance'); 
    aotInstance = ActionsOverTime.createActionOverTimeEmitter(config); 
    } 
})(); 

exports = aotInstance; 

これを行うと、新しいインスタンスが1回だけ作成され、ファイルが含まれるすべての場所で共有されます。変数がキャッシュされているかどうか、またはアプリケーションの内部参照メカニズム(キャッシュを含む可能性がある)のために変数がキャッシュされているかどうかはわかりません。どのようにノードがこれを解決するかについてのコメントは素晴らしいでしょう。

たぶんも作品を必要とどのように要点を取得するには、これを読んで: http://fredkschott.com/post/2014/06/require-and-the-module-system/

関連する問題