【问题标题】:How do I pass content from a template to a layout in Express?如何将模板中的内容传递到 Express 中的布局?
【发布时间】:2010-08-30 14:07:11
【问题描述】:

我有一个基本的 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 或简单的实例变量。)

【问题讨论】:

  • 虽然它是基于 DocPad 的 cms,但您可能会发现它很有用,因为它内置了对布局和玉石的支持。 github.com/balupton/docpad

标签: javascript node.js pug


【解决方案1】:

使用上面关于 dynamicHelpers 的技巧和闭包的魔力,我找到了一个相当优雅的解决方案,它可以在不涉及请求对象的情况下工作。诀窍是将页面标题变量包装在一个闭包中,该闭包提供围绕它的 get() 和 set() 函数,并使该包装对象成为 page_title 动态帮助程序的结果。

创建一个property.js:

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

所以调用 create() 会返回一个带有 get() 和 set() 方法的对象,用于获取和设置闭包变量。

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

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

由于动态帮助器的值是调用其函数的结果,因此在您的视图和模板中,page_title 变量将是带有 get() 和 set() 函数的包装对象。

在你看来,你可以说:

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

在你的布局中:

title= page_title.get()

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

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

让您将动态助手声明块简化为:

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

【讨论】:

  • 我遇到的闭包最实际的用途之一!
  • 您是如何在视图中实际使用它的?我喜欢这个想法,但对我来说 set() 函数永远不会被调用,并且 get() 始终为 null。
【解决方案2】:

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

传递的局部变量可用于布局和页面视图

【讨论】:

  • 所以想法是添加一个动态助手,在请求中存储pageTitle,然后布局可以读出?这听起来像是一个很好的解决方案。我什至可以把它包装成一个中间件并发布它!
【解决方案3】:

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');
...

轻松愉快。

【讨论】:

    【解决方案4】:

    您可以使用这个小 sn-p 来做到这一点。

    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') %>
    

    【讨论】:

      【解决方案5】:

      在本地传递它:{some: 'Locals', pageTitle: 'Welcome!'}

      【讨论】:

      • 我没有来自该模板的locals。我必须保留{ template path: page title } 的地图并在渲染之前查找页面标题。必须有一种方法可以从模板本身中指定它。
      【解决方案6】:

      对于 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()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-06
        • 1970-01-01
        • 2011-08-29
        • 2014-08-26
        • 2016-10-18
        • 1970-01-01
        • 1970-01-01
        • 2014-07-14
        相关资源
        最近更新 更多