Express 版本 4/5+ 的更新:
处理这个问题的最佳解决方案仍然是使用应用程序.locals如 Express API 参考中所述。正如此处的一些评论所指出的,API 在 Express 4 中进行了更新,以便app.locals
不再是一个函数,而只是一个对象。因此,如果您尝试将其作为函数调用,您将收到错误。
要在 Express 4/5+ 中使用 app.locals 来完成与下面 Express 3 的原始示例相同的操作,您可以设置app.locals
就像应用程序中可以访问 Express 的任何地方一样app
object:
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.title
, site.description
, author.name
, and author.contact
分别。
NOTE:或者,您也可以设置值app.locals
分别地。
例如,这也可以工作:
app.locals.authorName = 'Cory Gross';
app.locals.authorContact = '[email protected]';
但是,默认情况下,这将not工作,并且会抛出错误:
app.locals.author.name = 'Cory Gross';
app.locals.author.contact = '[email protected]';
发生这种情况是因为,虽然app.locals
已经作为 Express 公开的对象存在,您可以在其上定义属性,app.locals.author
尚不存在,因此上面的代码会抛出一个错误,抱怨您试图在未定义的对象上设置属性。为了执行上述操作,您首先必须设置app.locals.author = {}
作为一个空对象或只是将所有内容设置为app.locals
or app.locals.author
同时,类似于我上面的第一个例子。
中间件中的用法
虽然,设置的值app.locals
在所有视图中都可以全局访问,但在 Express 3 中使用它的潜在问题之一是默认情况下这些值不一定可以在中间件函数中访问。由于这一限制,一种替代方案,如最初建议的那样皮克尔的回答,正在将值设置为res.locals
相反,在顶级中间件中,以便这些值在所有较低的中间件以及所有视图中都可用。然而,这种替代方案有一个缺点,即设置所有这些值的逻辑将针对每个请求/响应一遍又一遍地执行,而不是像以下情况那样只设置一次并在服务器运行期间持续存在app.locals
.
在 Express 4/5+ 中,如果您想要设置的值,现在有更好的解决方案app.locals
可在中间件功能以及所有视图中使用。为了解决这个问题,Express 4/5+ API 现在公开了 Expressapp
所有中间件函数中的对象,可作为属性访问req
参数为req.app
。因此,默认情况下,您现在可以轻松访问设置的所有全局应用程序范围值app.locals
在所有中间件功能中以及简单地通过访问对象req.app.locals
在你的中间件中。
Express 版本 3 的原始答案:
在有机会学习之后Express 3 API 参考再多一点我就发现了我在寻找的东西。具体来说,条目为应用程序.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.title
, site.description
, author.name
, author.contact
.
我还可以为请求的每个响应定义局部变量res.locals
,或者简单地传递诸如页面标题之类的变量作为options
中的参数render
call.
EDIT:这个方法将not允许您在中间件中使用这些本地变量。事实上,正如皮克斯在下面的评论中所建议的那样,我确实遇到了这个问题。在这种情况下,您将需要在他的替代(和赞赏的)答案中创建一个中间件功能。您的中间件功能需要将它们添加到res.locals
对于每个响应,然后调用next
。该中间件函数需要放置在需要使用这些局部变量的任何其他中间件之上。
EDIT:通过声明当地人之间的另一个区别app.locals
and res.locals
是与app.locals
变量仅设置一次并在应用程序的整个生命周期中持续存在。当您设置当地人时res.locals
在您的中间件中,每次收到请求时都会设置这些。你基本上应该更喜欢通过设置全局变量app.locals
除非该值取决于请求req
变量传递到中间件。如果该值没有改变,那么只设置一次会更有效app.locals
.