从Jade模板中访问Express.js的req或session

29

我想知道是否有一种简单的方法可以在Jade模板中访问Express.js的req或session变量,而不需要通过正常响应传递它。

还是这是唯一的方法?

res.render('/', {
    session: req.session
});
8个回答

58

只需要添加

app.use(express.cookieParser());
app.use(express.session({secret: '1234567890QWERTY'}));
app.use(function(req,res,next){
    res.locals.session = req.session;
    next();
});

之前

app.use(app.router);

并在Jade中获取您的会话

p #{session}

2
谢谢。简单而实用。 - veinhorn
可能是最好的答案! - siva636
那真是非常简单和有用的 TAT - crazy_phage
这个不再起作用了。0|server | 错误:大多数中间件(如cookieParser)不再与Express捆绑在一起,必须单独安装。请参阅https://github.com/senchalabs/connect#middleware。 - sathia

46
在 express 3.x 中,dynamicHelpers 已被移除,因此您需要使用一些中间件和 res.locals 的组合。假设我们想在 /signup/new 视图中访问 req.query:

在 express 3.x 中,dynamicHelpers 已被移除,因此您需要使用一些中间件和res.locals的组合。假设我们要在/signup/new视图中访问req.query:

localQuery = function(req, res, next) {
  res.locals.query = req.query;
  next();
};

newSignup = function(req, res) {
  res.render('signup/new');
};

app.get('signup/new', localQuery, newSignup);

现在任何使用localQuery中间件的路由,都会设置res.locals.query。然后您可以在视图中将其访问为query


3
我为这个问题纠结了几个小时,你是我的救星 :) - Sushant Gupta

21
你需要创建一个dynamicHelper以供Express使用。
app.dynamicHelpers({
    session: function (req, res) {
        return req.session;
    }
});

然后在您的模板中,您可以使用 <%= session.logged_in %> 或其他内容。

注意:Express 3 中已不建议使用 dynamicHelpers。


3

这对我非常有效

app.use(function(req,res,next){
   res.locals.user = req.user;
   next();
});

在 Pug 或 Jade 视图中,用户

#{user.email}

3

只需使用中间件。

app.use(function (req, res, next) {
            var origRender = res.render;
            res.render = function (view, locals, callback) {
                if ('function' == typeof locals) {
                    callback = locals;
                    locals = undefined;
                }
                if (!locals) {
                    locals = {};
                }
                locals.req = req;
                origRender.call(res, view, locals, callback);
            };
            next();
});

在此之后,您可以使用"#{req}"在jade模板中引用它。

假设您在'req'中有一个'user'对象,并且'user'有一个名为'isAnonymous'的方法,如果您的user.isAnonymous()返回true,

p #{req.user.isAnonymous()}

将被渲染为:

<p>true</p>

0

虽然在JavaScript中总有一种方法可以逃脱作用域并向上爬,但我真的非常强烈建议您找到另一种方法。

考虑一下你所要求的:我的视图是否可以知道控制器的内部细节?

或者你真正想问的是:我的视图是否可以知道运行时的内部细节?

视图应该将数据转换为标记。这就是它的作用。如果你做了其他事情,那么你就错了。我不在乎这有多“容易”。这就是接口的目的。定义传递的内容,并使其易于用另一个东西替换。


8
这个回答有点严厉,也没有提供帮助。我和其他人一样遵循一些严格的MVC指南,但在这种情况下,我们谈论的是一个html模板中的if()语句。考虑到另一个选项是为登录和未登录用户分别准备两个完全不同的模板,破坏一些MVC规则会成为较小的恶。 - Jonathan Dumaine
3
不是真的。我会从控制器传递数据,我不希望视图知道如何调用其他模型。我不介意视图具有分支逻辑、计数器/迭代器和循环,但这就是它应该具有的所有逻辑。我只会传递数据,我与其他做MVC的人交流时也是这样的。 - jcolebrand
由于大多数Node.js程序不仅仅是“视图”和“模型”,所以是的。 - jcolebrand
为每个路由传递相同的数据违反了DRY原则。 - tomdemuyt
这取决于您如何呈现响应。一个函数返回另一个调用的值并不违反DRY原则。最多可以说,“为每个路由传递相同的数据可能会违反DRY原则”。 - jcolebrand
显示剩余2条评论

0
如果您的会话对象变量是全局声明的,则
在全局中
var sess
在函数中

sess=req.session

req.render('index.pug',{sess})


0

你可以通过一个渲染函数来解决这个问题,在该函数中,你可以将需要会话变量的每个视图都呈现为在模板中可访问的本地变量(通常是当用户已登录时)。

以下是一个函数示例,但你可以根据需要进行调整:

var renderView = function(res, template, context, session, cb) {
    context.session = session;

    if(cb){
        res.render(template, context, function(error, html){
            cb(error, html)
        }
    } else {
        res.render(template, context)
    }
}

然后可以像这样使用:

app.get("/url", function(req, res){

    req.session.user_email = user_email;

    renderView(res, "template_name", { local_variables: local_variables }, req.session)
});

在您的jade模板中,您可以像这样访问会话变量:

div.user-email #{session.user_email}

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