简体   繁体   English

Express Middleware为所有app.get()填充Jade变量

[英]Express Middleware to populate a Jade variable for all app.get()'s

I have a Jade file that all of my templates extend called layout.jade. 我有一个Jade文件,我的所有模板都扩展名为layout.jade。 In it I want to be able to have a logout button if the user is currently logged in (this is kept track of in req.session). 在其中我希望能够在用户当前登录时具有注销按钮(这在req.session中保持跟踪)。

So layout.jade will have something like, 所以layout.jade会有类似的东西,

-if (loggedin)
  a.navButton(href="/logout") Log Out

The route for a page would look something like, 页面的路径看起来像,

app.get("/foo", function(req, res) {
    res.render("foo", {loggedin: req.session.isValidUser});
});

The thing is, I don't want to have to populate the loggedin variable manually in every single route. 问题是,我不想在每个路由中手动填充登录变量。 Is there a way I can use Express middleware to automatically set some default options for the object sent to res.render? 有没有办法可以使用Express中间件自动为发送到res.render的对象设置一些默认选项? Or is there a better method to do this? 或者有更好的方法来做到这一点?

Basically I'm asking how I can have some set of variables always sent to templates, as well as the ability to have certain custom variables available in certain templates by manually setting them in the routes. 基本上我问我怎样才能将一些变量总是发送到模板,以及通过在路径中手动设置某些模板中某些自定义变量的功能。

It seems this is actually a documented feature I just had trouble finding, unless anyone has a better way of doing it; 看起来这实际上是一个我很难找到的记录功能,除非有人有更好的方法去做; From the latest Express documentation , 从最新的Express文档中

app.locals : Application local variables are provided to all templates rendered within the application. app.locals :应用程序局部变量提供给应用程序中呈现的所有模板 This is useful for providing helper functions to templates, as well as app-level data. 这对于为模板提供辅助函数以及应用程序级数据非常有用。

So in my login success function has, 所以在我的登录成功函数中,

req.session.username = profile.username;
app.locals.username = profile.username;

My logout function, 我的退出功能,

app.get('/logout', function (req, res) {
    delete app.locals.username;
    req.session.destroy();
    res.redirect('/login');
});

And finally in layout.jade/all of my templates, 最后在layout.jade /我的所有模板中,

- if(username)
  a.navButton(href="/logout") Logout

If you set res.locals.loggedin in the /login route, as hexacyanide suggests, this local will not be available in the route for /foo . 如果你在/login路由中设置res.locals.loggedin ,正如hexacyanide建议的那样,这个本地将不会/foo的路由中可用。 res.locals is cleared upon every request. 每次请求都会清除res.locals

you could instead try placing this above other routes: 您可以尝试将其置于其他路线之上:

app.all('*', function(req, res, next){
  if(req.user){
    res.locals.loggedin = true;
    res.locals.currentuser = req.user;
  };
  next();
});

Pretty sure that if you modify req.user during your route, the res.locals.currentuser that you set before won't updated to be the new req.user . 非常确定如果在路由期间修改req.user,则之前设置的res.locals.currentuser将不会更新为新的req.user but not certain about that. 但不确定。

I actually use a custom render function for each page where I render a template, it looks like this: 我实际上为每个渲染模板的页面使用自定义render功能,它看起来像这样:

function myRender(templateName){
  return function(req, res){
    res.locals.currentuser = req.user || null;
    res.render(templateName);
  };
};

and I use it like this: 我这样使用它:

app.get('/foo'
, function(req, res, next){
  res.locals.bar = req.query['bar'] || "";
  console.log('passing request to myRender middleware');
  next();
}
, myRender('foo-jade-template')
)

This has the advantage of only setting res.locals.currentuser when I am ready to render something, instead of before executing my route. 这样做的好处是,当我准备渲染某些内容时,而不是在执行我的路由之前,只设置res.locals.currentuser So if I change req.user it is guranteed to have the most recent version at render time. 因此,如果我更改req.user ,则保证在渲染时具有最新版本。

There is a line of code that is rather useful to you in the Express source: 在Express源代码中有一行对您非常有用的代码:

// merge res.locals
options._locals = self.locals;

Therefore, when you run res.render() , Express will also take any locals that are stored in res.locals and pass them into the render. 因此,当您运行res.render() ,Express还将获取存储在res.locals所有本地res.locals并将它们传递给渲染。 Therefore, all you have to do is set res.locals.loggedin to true, and then run res.render() as usual. 因此,您所要做的就是将res.locals.loggedin设置为true,然后像往常一样运行res.render()

app.get('/login', function(res, res) {
  res.locals.loggedin = true;
});
app.get('/foo', function(req, res) {
  res.render('foo', {});
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM