Node.js + Express + Hogan.js中的部分视图模板

18
我正在使用Node.js + Express开发一个网站,并使用Hogan.js作为视图引擎。这是我的文件app.js:
/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path');

var app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'hjs');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser('your secret here'));
  app.use(express.session());
  app.use(app.router);
  app.use(require('less-middleware')({ src: __dirname + '/public' }));
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

app.get('/', routes.index);
app.get('/about', routes.about);
app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

文件/routes/index.js是:

/*
 * GET pages.
 */

exports.index = function(req, res){
  res.render(
    'index',
    {
      title: 'Home Page',
      author: 'Bruce Wayne'
    }
  );
};

exports.about = function(req, res){
  res.render(
    'about',
    {
      title: 'About Page',
      author: 'Bruce Wayne'
    }
  );
};

/views 文件夹中,有以下文件:

|- part.hjs

|- index.hjs

|- cv.hjs

文件 part.hjs 是:

<h3>Hello {{ author }}</h3>

文件 index.hjs 是:

<h1>Title: {{ title }} </h1>
{{> part }}
Welcome to Gotham City.

而文件about.hjs是:

<h1>Title: {{ title }}</h1>
{{> part }}
I'm not Joker.

我有两个问题:

  1. 如何在我的页面中正确使用partials? (这段代码无效)
  2. 在文件/routes/index.js中不重复分配值的情况下,是否可以在两个或多个页面中使用相同的"title"?

最好的问候,Vi。


感谢您发布这个问题。天哪,我在谷歌上搜索了一会儿,直到偶然发现了这颗宝石。 - FinalForm
我认为Oren的答案是这个问题的正确答案。 - bryanmac
1
你在这里运行的是哪个版本的Express? - martisj
什么是partial? - Martín Nieva
6个回答

25

我已经找到了第一个问题的解决方案。

首先,我移除了hjs

npm remove hjs

然后,我安装了 hogan-express 包:

npm install hogan-express

此外,我编辑了app.js文件:
/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path');

var app = express();

app.engine('html', require('hogan-express'));
app.enable('view cache');

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'html');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser('your secret here'));
  app.use(express.session());
  app.use(app.router);
  app.use(require('less-middleware')({ src: __dirname + '/public' }));
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

app.get('/', routes.index);
app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

并在 routes/index.js 中:

exports.index = function(req, res) {
  res.locals = {
    title: 'Title',
  };
  return res.render(
    'index',
    {
      partials:
      {
        part: 'part',
      }
    }
  );
};

现在,在 /views 目录下有 index.htmlpart.html 两个文件。 文件 part.html 包含以下内容:

<h1>{{ title }}</h1>

文件 index.html 包含以下内容:
{{> part}}
Hello world!

所以,它工作得很好。


1
现在不需要删除 hjs,只需在 render 中添加 partials:{ var: file_path } 即可。 - user1775888
1
@user1775888 是正确的... 至少对于 Express 4+。我在另一个答案中进行了扩展。 - bryanmac

6

至少在Express 4+中,部分视图无需任何配置即可正常工作。你可以使用npm安装express-generator,并使用--hogan或-H选项。

之后,你需要将部分视图添加到render方法中:

router.get('/', function(req, res, next) {
  res.render('index', 
        { 
            title: 'My Site',
            partials: {header: 'header'} 
        });
});

然后,在你的模板中使用{{ > xxx }}
<body>
  {{> header }}
  <h1>{{ title }}</h1>

  <p>Welcome to {{ title }}</p>
</body>

注意:视图中有header.hjs


4
要在express+hogan中使用partials,只需按照以下步骤操作:
app.get('/yourRoute', function(req, res){  
   res.render('yourPartial', function(err,html){
       var partialHTML = html;
       res.render('yourMainView', { myPartial: partialHTML }, function(err,html){
          res.send(html);   
       });     
   });
}

现在,您的MainView.html文件如下:

<p>Something Something Something</p>
{{{partialHTML}}}
<p>Bla Bla Bla</p>

注意使用三个 '{' 而不是平常用的两个! 这会告诉 hogan (mustache) 把这个解析为 HTML 而不是字符串!

就是这样。


你知道如何将HTML内容分配给JavaScript变量吗?就像这样:<script> var html = '{{{partialHTML}}}'; </script> 但是需要考虑HTML转义字符等安全性问题。 - cmarrero01

3
关于您的partials问题,如果您使用consolidate.js,您可以简单地执行以下操作:
res.render('index', {
  partials: {
    part  : 'path/to/part'
  }
});

2

我建议使用mmm代替hjs

https://github.com/techhead/mmm

免责声明:这个包是我写的。

只需将所有hjs替换为mmm,部分视图就可以开始工作了。有更多信息和示例,请参见上面的链接。

至于您的另一个问题,如果您想在多个视图之间共享属性,则有几个选项。

当您调用res.render(name, options)时,实际上会将options合并到res.localsapp.locals中,然后再传递给渲染引擎。因此,要设置应用程序范围的属性,您可以简单地将其分配给app.locals

app.locals.title = "Default Title"; // Sets the default title for the application

这个概念适用于几乎所有的Express 3视图引擎。但是,对于mmm,请查看“表现逻辑”部分,以获取将值绑定到模板或一组模板的更多方式。

我也遇到了类似的问题,我不想采用下一个解决方案并显式地将partials变量传递给我的模板。我现在要尝试一下mmm。希望这次能成功。我已经尝试过hulk-hogan,只是发现它不支持express 3.x。 - Naman Goel
不好的建议。如果 OP 已经使用 hjs 做了大量工作,那么更改模板引擎来解决这样一个简单的问题是过度杀伤力的。 - Paul Allsopp

2

这是一个问题。在Express 3中很难获得部分支持。

您最好的选择是: https://github.com/visionmedia/consolidate.js npm install consolidate

这些补丁采用了不同的方法来添加Hogan的部分:

不幸的是,该引擎本身没有针对基于文件系统的部分的钩子,因此我认为人们对应该如何以及在哪里实现部分感到困惑。我最终选择了LinkedIn的Dust.js实现,因为部分支持已经存在。Master实际上具有更好的支持,而且昨天我提交了一个有关相对路径的补丁。

Josh


非常感谢。我可以使用hogan-express包找到partials的解决方案。与consolidate有什么区别?哪个更好? - user1288707
1
Consolidate可能已经支持partials。在下面你列出的解决方案中,你必须提前声明所有的partials并将它们传递到选项哈希中。这有点不方便,但也不是无法处理的。在其他语言中,你只需要说{>partial/},它就会直接从文件系统中拉取partial。 - Josh

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