45

我正在使用 Express.js(在 Node.js 上),我知道您可以通过“locals”参数呈现带有自定义数据的视图。( res.render("template", { locals: { foo: "bar" } });)

有没有办法拥有“全局”?(即每个视图都可以访问的数据)

我看到了view options,但这不是递归的,所以如果我在模板中使用任何本地人,它会替换我设置的本地人。

这是我的用例:我想让它可以在每页的基础上添加 CSS/JS 文件,这是我主要布局的一部分。问题是,如果我没有在每个渲染上明确设置这些数组,我会得到一个未定义的错误,所以在我的模板中我总是不得不typeof css !== "undefined"跳舞。此外,我还有其他选择框选项列表,我不想明确添加到我的每个表单中。

4

7 回答 7

57

对于自 Express 3 发布以来可能遇到过这个问题的人来说,值得注意的是,方法 'dynamicHelpers' 不再存在。

相反,您可以使用 app.locals 函数,它充当可以存储值或函数的对象,然后使它们可用于视图。例如:-

// In your app.js etc.
app.locals.title = "My App";
app.locals({
    version: 3,
    somefunction: function() {
        return "function result";
    }
});

// Then in your templates (shown here using a jade template)

=title
=version
=somefunction()  

// Will output

My App
3
function result

如果您需要访问请求对象以从中提取信息,您可以编写一个简单的中间件函数并使用 app.settings 变量。

例如,如果您使用 connect-flash 向您的用户提供消息,您可能会执行以下操作:

app.use(function(req, res, next) {
    app.set('error', req.flash('error'));
    next();
});

这将使您可以使用模板中的 =settings.error 访问错误消息。

此处涵盖了这些主题,尽管内容略显简短:http ://expressjs.com/api.html#app.locals

更新:快递 4

app.locals现在是一个简单的 JavaScript 对象,所以每个属性都必须一个一个地设置。

app.locals.version = 3;
app.locals.somefunction = function() {
    return "function result";
}

res.locals提供完全相同的功能,除了它应该用于特定于请求的数据而不是应用程序范围的数据。用户对象或设置是一个常见的用例。

res.locals.user = req.isAuthenticated() ? req.user : null;
res.locals.userSettings = {
    backgroundColor: 'fff'
}
于 2012-10-13T17:18:42.670 回答
10

有一种方法可以使用动态视图助手为视图提供“全局”变量。

来自 Express.js 指南:

app.dynamicHelpers(obj)

注册动态视图助手。动态视图助手是简单的函数,它们接受 req、res 并在呈现视图之前针对服务器实例进行评估。该函数的返回值成为与其关联的局部变量。

app.dynamicHelpers({ session: function(req, res){ return req.session; } });

所有视图现在都可以使用会话,以便可以通过 session.name 等访问会话数据:

您可以在此处找到有关如何使用它们的真实示例:https ://github.com/alessioalex/Nodetuts/tree/master/express_samples (节点 app.js 启动应用程序)

于 2011-06-16T10:41:18.870 回答
8

作者提到的使用视图选项的真实示例:

var app = express.createServer();

app.configure(function() {
  app.set('views', path.join(__dirname, '..', 'views'));
  app.set('view engine', 'jade');
  app.set('view options', {
    assetVersion: 1
  });

然后在我的 layout.jade (在我的例子中是应用程序的基本模板):

link(rel='stylesheet', href='/static/css/' + assetVersion + '/style.css')
script(src='/static/js/' + assetVersion + '/script.js')

有了这个小技巧,我只需要在assetVersion一个地方更新变量,以确保我的资产没有缓存在 Varnish 或其他地方。

于 2011-12-24T21:04:12.033 回答
4

我最终查看了源代码,实际上我发现这现在在 Express 的任何版本中都是可能的。(到目前为止,只能通过 GitHub 获得)

于 2011-01-19T21:17:00.380 回答
1

完成此操作的最简单方法是创建一个变量,该变量代表视图的默认局部变量集。然后创建一个接受对象的函数,将其与局部变量合并,并返回合并后的对象。

我还在一个容器对象中传递我的所有本地人,{locals:{g:{prop:val}}} 在我的视图中我可以引用它,当它没有设置时它g.prop会返回,而不是抛出一个未定义的错误。null

function default_page_vars(custom_vars){
    var vars = {
        footer: true,
        host: req.headers.host.split(':')[0],
        config: this.config
    };

    if(custom_vars){
        for(var k in custom_vars){
            vars[k] = custom_vars[k];
        }
    }
    return {
        g:vars
    };
}

//within your handler
response.render(view, {
    locals: default_page_vars(other_locals)
});
于 2011-01-18T22:48:20.290 回答
0

这是一个隐藏的响应,但我终于让它起作用了。

1)这是一个围绕模块连接闪存的例子

2)在 server.js/app.js 中添加一个中间件以添加reqlocals. 这允许模板在request.flash()需要时调用。没有这个,flash()每个请求/重定向都会消耗掉这个目的。

var app = module.exports = express()
  , flash=require('connect-flash');
app.configure(function(){
  ...
  app.use(express.session({ secret: "shhh" }));

  // Start Router
  app.use(flash());
  app.use(function(req, res, next) {
    res.locals.request = req;
    next();
  });

  app.use(app.router);
});

3)正常设置你的路线(这是coffeescript,但没什么特别的)

app.get '/home', (req, res) ->
  req.flash "info", "this"
  res.render "#{__dirname}/views/index"

4) 当你想要消息时调用 request.flash() 。每次通话都会消耗它们,所以不要控制台记录它们,否则它们会消失 :-)

!!!
html
  head
    title= config.appTitle
    include partials/_styles

  body
    include partials/_scripts

    #header
      a(href="/logout") Logout CURRENTUSER
      h2= config.appTitle

    #messages
      - var flash = request.flash()
      each flashType in ['info','warn','error']
        if flash[flashType]
          p.flash(class=flashType)
            = flash[flashType]


    block content
      h1 content here
于 2013-06-19T03:03:19.383 回答
0

快递4

您可以访问应用程序中呈现的模板中的局部变量。

所以,如果你想在你的模板中使用任何本地变量 => 假设你有一个模板引擎 npm 安装到你的 node/express 应用程序中。

首先,您需要在文件中使用您的自定义变量设置express locals 对象app.js,如果需要多个值,您可以使用一个对象(我们在这篇文章中的例子)

 /**
  *  Set locals object
  */

 app.locals.layoutData = { 
  site: {
      title: 'MyWebSiteTitle',
  },   
  metaTag: {
      charset: 'UTF-8',
      description: 'MyDescription',
      keywords: 'keyword-1,keyword-2,...',
      author: 'MyName',
      viewport: 'width=device-width, initial-scale=1.0'
  }
 };

然后,访问模板文件中的值layout.pug(以 PUG 模板引擎为例)

doctype html
html
  head
    //title
    title #{locals.layoutData.site.title}
    //Describe metadata
    meta(charset=layoutData.metaTag.charset)
    meta(name='description', content=locals.layoutData.metaTag.description)
    meta(name='keywords', content=locals.layoutData.metaTag.keywords)
    meta(name='author', content=locals.layoutData.metaTag.author)
    meta(name='viewport', content=locals.layoutData.metaTag.viewport)
  body
      block content
      br
      hr
      footer
        p All rights reserved © 2018 |  #{locals.layoutData.site.title}

经测试

  "dependencies": {
    "express": "^4.16.3",
    "pug": "^2.0.3"
  }
于 2018-06-20T17:22:16.617 回答