如何将内容从模板传递到Express中的布局?

我有一个基本的Express服务器:

// server.js: var Express = require('express'); app = Express.createServer(); app.configure(function(){ app.set('views', Path.join(__dirname, 'views')); app.set('view engine', 'jade'); app.set('view options'); }); app.get('/', function (request, response) { response.render('welcome', { locals: {some: 'Locals'} }); }); 

基本的玉石布局:

 // views/layout.jade: !!! 5 html(lang='en') head title= pageTitle body h1= pageTitle aside(id="sidebar")= sidebarContent #content #{body} 

和一个简单的页面:

 # views/welcome.jade: // How do I pass pageTitle and sidebarContent out to the layout from here? p Welcome to my fine site! 

(在Rails中,这可能类似于content_for或简单的实例variables。)

使用上面关于dynamicHelpers的技巧,以及闭包的魔力,我发现了一个相当优雅的解决scheme,它不涉及请求对象。 诀窍是将页面标题variables包装在一个闭包中,该闭包提供一个get()和set()函数,并使该包装对象成为page_titledynamic助手的结果。

创build一个property.js:

 exports.create = function () { var value = null; return { get: function () { return value; }, set: function (new_value) { value = new_value; } }; } 

所以调用create()方法返回一个get()和set()方法的对象,它获取并设置闭包variables。

然后,在您的应用程序的设置代码中:

  var property = require("./property.js"); app.dynamicHelpers ({ page_title: function () { return property.create (); } }); 

由于dynamic助手的值是调用它的函数的结果,因此在视图和模板中,page_titlevariables将作为包含get()和set()函数的包装对象。

在你看来,你可以这样说:

 - page_title.set ("my specific page title"); 

并在您的布局:

 title= page_title.get() 

为了进一步简化这一点,将其添加到property.js中:

 exports.creator = function () { return function () { return exports.create(); }; } 

让你简化dynamic助手声明块到这个:

  var property = require("./property.js"); app.dynamicHelpers ({ page_title: property.creator() }); 

Express没有先入为主的“块”概念,或者他们在rails中调用的任何概念,但是可以使用helpers()和dynamicHelpers()的组合来实现类似http://expressjs.com/guide.html# APP-佣工,obj-

虽然传递的本地可用于布局和页面视图

layout.jade

 # the following function is a safe getter/setter for locals - function pagevar(key, value) { var undef; return (value===undef) ? locals[key] || null : locals[key] = value; } block config #intended as a non-rendered block so that locals can be overridden. # put your defaults here... - use append in the child view !!! html head title=pagevar('title') meta(name='description',content=pagevar('description')) ... 

page.jade

 append config - locals.title = 'override'; - locals.description = 'override 2'; - pagevars('somekey', 'some value'); ... 

轻松的pe。。

你可以通过使用这个小片段来做到这一点。

prop.js:

 var hash = {}; module.exports = function() { return { set: function(key, val) { hash[key] = val }, get: function(key) { return hash[key] } }; }; 

server.js:

 app.dynamicHelpers({ prop: require(__dirname + '/views/helpers/prop') }); 

视图:

 <% prop.set('foo', 'bar') %> 

布局:

 <%= prop.get('foo') %> 

传递给当地人: {some: 'Locals', pageTitle: 'Welcome!'}

对于Express 3模板不可知,适用于express-partials

 app.use (req, res, next)-> req.locals = {} unless req.locals res.locals.content_for = (k, v = null)-> if !v req.locals[k] else req.locals[k] = v next()