如何使用Express / Node.JS创build在所有视图中可访问的全局variables?
好的,我已经使用Jekyll创build了一个博客,您可以在_config.yml
文件中定义可在所有模板/布局中访问的variables。 我正在使用Node.JS / Express与EJS模板和ejs-locals (用于partials / layouts)。我正在寻找类似于像_config.yml
中find的site.title
这样的全局variables,如果有人熟悉Jekyll 。我有像网站的标题,(而不是页面标题),作者/公司名称,在我的所有网页上保持相同的variables。
这是我目前正在做的一个例子。
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 }); };
我希望能够在一个地方定义像我的网站的标题,描述,作者等variables,并通过EJS在我的布局/模板中访问它们,而不必将它们作为选项传递给res.render
。 有没有办法做到这一点,仍然允许我传递其他variables特定于每个页面?
在有机会学习Express 3 API Reference之后,我发现了一些我正在寻找的东西。 具体来说, app.locals
的条目,然后再往下res.locals
举行我需要的答案。
我发现自己的functionapp.locals
接受一个对象,并将其全部属性存储为应用程序的全局variables。 这些全局variables作为局部variables传递给每个视图。 然而, res.locals
函数的作用范围是这个请求,因此响应局部variables只能在特定请求/响应期间呈现的视图访问。
所以对于我的情况在我的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: 'CoryG89@gmail.com' } });
然后所有这些variables都可以在我的意见作为site.title
, site.description
, author.name
, author.contact
。
我也可以使用res.locals
为每个请求的响应定义局部variables,或者简单地像render
调用中的options
参数那样传递像页面标题一样的variables。
编辑:这种方法不会让你在你的中间件中使用这些当地人。 我实际上是在Pickels在下面的评论中提到的。 在这种情况下,您将需要创build一个中间件function在他的替代(和赞赏)的答案。 您的中间件function需要将它们添加到每个响应的res.locals
中,然后再调用。 这个中间件function将需要放在任何其他需要使用这些本地中间件的中间件之上。
编辑:通过app.locals
和res.locals
声明当地人之间的另一个区别是与app.locals
variables设置一个单一的时间,并坚持贯穿整个应用程序的生活。 当您在中间件中设置了res.locals
本地res.locals
时,每当您收到请求时都会设置这些文件。 你应该更喜欢通过app.locals
设置全局variables,除非值取决于传入中间件的请求variables。 如果这个值没有改变,那么它会在app.locals
设置一次效率app.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(); });
当地人也是一个扩大当地人对象而不是覆盖它的function。 所以下面的工作也是如此
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,这意味着你有更好的代码重用。 一旦你下了可重用的中间件路线,你会注意到你将会有很多积木,这将加速发展。
对于Express 4.0,我发现使用应用程序级别variables的工作方式稍有不同,Cory的答案对我来说不起作用。
从文档: http : //expressjs.com/en/api.html#app.locals
我发现你可以在应用程序中声明一个全局variables
app.locals
例如
app.locals.baseUrl = "http://www.google.com"
然后在您的应用程序中,您可以访问这些variables,在您的快递中间件中,您可以在req对象中访问它们
req.app.locals.baseUrl
例如
console.log(req.app.locals.baseUrl) //prints out http://www.google.com
在你的app.js中,你需要添加这样的东西
global.myvar = 100;
现在,在你想要使用这个variables的所有文件中,你可以像myvar
那样访问它
一种方法是通过更新app.js
该app的app.locals
variables
通过以下设置
var app = express(); app.locals.appName = "DRC on FHIR";
获取/访问
app.listen(3000, function () { console.log('[' + app.locals.appName + '] => app listening on port 3001!'); });
从@RamRovi示例的屏幕截图进行细化,略有增强。
你也可以使用“全球”
例:
声明如下:
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);
我为了避免受到污染的全球范围所做的是创build一个脚本,我可以将其包含在任何地方。
// 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;
这样做只会创build一个新的实例,并在文件所在的位置共享。 我不确定是因为variables被caching还是因为应用程序的内部引用机制(可能包括caching)。 有关节点如何解决这个问题的任何意见将是伟大的。
也许还可以阅读这个获得如何工作的要点: http : //fredkschott.com/post/2014/06/require-and-the-module-system/