ExpressJS 3.0如何将res.locals传递给jade视图?

20

我想在用户登录失败后显示一条闪存消息,但我无法让变量显示在我的Jade视图中。

我有一些代码片段,我知道我必须在我的app.configure()函数中使用它:

    app.use (req, res, next) ->
      res.locals.session = req.session

当用户输入错误的密码时,我会在用户提交POST请求后设置闪现消息:

     exports.postSession = (req, res) ->
       users = require '../DB/users'
       users.authenticate(req.body.login, req.body.password, (user) ->
       if(user)
         req.session.user = user
         res.redirect(req.body.redirect || '/')
       else
         req.session.flash = 'Authentication Failure!'
         res.render('sessions/new', {title:'New', redirect: req.body.redirect })
      )
我不知道如何在我的Jade文件中访问res.locals.session。我怀疑我没有正确设置一切。这个问题很像这个问题:Migrating Express.js 2 to 3, specifically app.dynamicHelpers() to app.locals.use?,但我仍然不能让它工作。如果有人能向我展示一个简单的例子,在res.local中设置值并在视图中访问它们,那将不胜感激。
附言:我确实知道connect-flash,但我需要了解如何在视图中使用它。
这是我的应用程序:
app.configure(() -> 
  app.set('views', __dirname + '/views')
  app.set('view engine', 'jade')
  app.use(express.bodyParser())
  app.engine('.jade', require('jade').__express)
  app.use(express.methodOverride())
  app.use(express.cookieParser())
  app.use(express.session({ store: new express.session.MemoryStore({reapInterval: 50000 * 10}), secret: 'chubby bunny' }))
  app.use(express.static(__dirname + '/public'))
  app.use((req, res, next) ->
    res.locals.session = req.session
    next()
  )
  app.use(app.router)
)

你不能通过 session.flash 访问它吗? - Jonathan Ong
我不知道app.use在app.router或app[VERB]方面的区别。在我的理解中,它是用于路由器的,因为在路由请求之前,这些语句在服务器的当前状态下进行评估...但我不确定在app[VERB]的上下文中,app.use是什么意思。 - aeyang
1
app[VERB] 是指像 app.get、app.post 这样的东西。这些都是在 app.use(app.router) 中的路由,应该放在除任何错误处理程序之外的任何其他 app.use 之后。你把它们放在什么顺序? - Jonathan Ong
哦,好的,我的app.use(app.router)肯定是在我的app.use(req, res, next) -> res.locals.session = req.session之后。所以除了我的app.use()语句的顺序之外,这基本上是创建res.local变量的方法吗?此外,我正在尝试在我的布局文件中访问这些res.local变量。我不认为这是问题,但是是否有限制哪些视图可以访问您的res.locals? - aeyang
不,没有。你能直接发布你的应用程序吗? - Jonathan Ong
显示剩余7条评论
2个回答

38

针对所有遇到相同问题,认为通过更改 res.redirect 已经解决的人,这里提供一个简短的总结。

非常重要的一点是,在 app.router 之前放置 app.use 中间件。请查看 express 的作者 TJ Holowaychuck 的注释。

以下是使用 express v3.0.0rc4 新安装的实例:

app.js:

app.use(function(req, res, next){
  res.locals.variable = "some content";
  next();
})

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

index.jade:

extends layout

block content
  h1= title
  p Welcome to #{title}
  p= variable

是的,谢谢您。请忽略问题下面的评论,这就是解决方法。 - aeyang
很高兴能够帮上忙!你想正式接受这个答案吗? - zemirco
将 app.use 放在 app.router 之前可以正确地在视图中传递 locals 值。 - peter

9

如果您正在使用express.session(),则必须在app.configure()中的express.session()之后但在app.router之前调用您的函数。

app.js

app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.session());

  // Give Views/Layouts direct access to session data.
  app.use(function(req, res, next){
    res.locals.session = req.session;
    next();
  });

  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

index.jade

extends layout

block content   
  h1= title   
  p My req.session.var_name is set to #{session.var_name}

这背后的原因是什么? - gprasant
我目前在express.session()之前使用它,为什么应该避免使用它? - Jim Factor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接