如何使用Express/Node.JS创建可在所有视图中访问的全局变量?

Cor*_*oss 75 template-engine ejs node.js express sails.js

好的,所以我使用Jekyll构建了一个博客,您可以在文件中定义_config.yml可在所有模板/布局中访问的变量.我目前正在使用带有EJS模板和ejs-locals的Node.JS/Express(用于局部 /布局.我希望做一些类似于全局变量的东西,如果有人熟悉Jekyll的话.我有类似的变量网站的标题,(而不是网页标题),作者/公司名称,在我的所有网页上保持不变.site.title_config.yml

这是我目前正在做的一个例子:

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
    });
};
Run Code Online (Sandbox Code Playgroud)

我希望能够在一个地方定义像我的网站的标题,描述,作者等变量,并让他们通过EJS我的布局/模板访问,而无需通过他们的选项,每次调用res.render.有没有办法做到这一点,仍然允许我传递特定于每个页面的其他变量?

Cor*_*oss 102

在有机会研究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: 'CoryG89@gmail.com'
    }
});
Run Code Online (Sandbox Code Playgroud)

然后,所有这些变量都在我的意见,访问site.title,site.description,author.name,author.contact.

我还可以为请求的每个响应定义局部变量res.locals,或者简单地将变量(如页面的标题)作为调用中的options参数传递render.

编辑:此方法将不会让你在你的中间件使用这些本地人.我确实碰到了这一点,正如Pickels在下面的评论中所暗示的那样.在这种情况下,您需要在他的替代(和赞赏)答案中创建一个中间件功能.您的中间件功能需要res.locals为每个响应添加它们然后调用next.这个中间件功能需要放在需要使用这些本地的任何其他中间件之上.

编辑:通过宣布当地人之间的另一个不同之处app.locals,并res.locals是与app.locals这些变量设定一个时间,坚持在整个应用程序生命周期.res.locals在中间件中设置本地文件时,每次收到请求时都会设置这些文件.app.locals除非值取决于req传递给中间件的请求变量,否则您基本上更喜欢设置全局变量.如果值没有改变,那么只设置一次就会更有效率app.locals.

  • 在**Express 4**`locals`不是一个函数,而是一个对象.设置属性:`app.locals.site.title ='示例';` (48认同)

Pic*_*els 50

您可以通过将它们添加到常规中间件中的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();
});
Run Code Online (Sandbox Code Playgroud)

Locals也是一个扩展locals对象而不是覆盖它的函数.所以以下工作也是如此

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

完整的例子

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'));
Run Code Online (Sandbox Code Playgroud)

我还添加了一个通用的渲染中间件.这样您就不必为每条路由添加res.render,这意味着您可以更好地重用代码.一旦你沿着可重复使用的中间件路线走下去,你会发现你将拥有许多构件,这将大大加快开发速度.


Ram*_*ovi 17

对于Express 4.0,我发现使用应用程序级变量的工作方式略有不同,Cory的答案对我不起作用.

来自文档:http://expressjs.com/en/api.html#app.locals

我发现你可以为应用程序声明一个全局变量

app.locals
Run Code Online (Sandbox Code Playgroud)

例如

app.locals.baseUrl = "http://www.google.com"
Run Code Online (Sandbox Code Playgroud)

然后在您的应用程序中,您可以访问这些变量,并在您的快速中间件中,您可以在req对象中访问它们

req.app.locals.baseUrl
Run Code Online (Sandbox Code Playgroud)

例如

console.log(req.app.locals.baseUrl)
//prints out http://www.google.com
Run Code Online (Sandbox Code Playgroud)

  • 此外,当在代码中添加新的本地人时,需要重新启动快速服务器。 (2认同)

小智 12

在你的app.js中你需要添加这样的东西

global.myvar = 100;
Run Code Online (Sandbox Code Playgroud)

现在,在您想要使用此变量的所有文件中,您只需访问它即可 myvar

  • 实际上,这不建议或被认为是Node开发中的一个好习惯.Node.JS包括基于CommonJS系统的模块系统实现,并且完全集中在不共享全局范围的模块的概念上,而是使用require方法.这也设置了Node中的全局js var而不是像问题所要求的Express视图/模板的本地. (6认同)