如何使用Node.js,EJS模板和动态文件名进行多重渲染

时间:2014-06-30 12:46:34

标签: javascript node.js templates express ejs

我将Node.js与Express和EJS模板一起使用,我想动态管理我的HTML Templace ..

这次,我有:

- server.js
- views/
- - template.ejs
- - layout.ejs 

在我的server.js中,我使用数据加载模板视图,并使用<% include %>在模板上加载布局:

server.js

var data = { some: 'stuff'};
res.render('template', data);

template.ejs

<% include layout %>

在这个时刻,代码工作得很好,我有预期的结果。

但是现在,我想要一个数据变量,说布局的文件名,可以在layouts /目录中找到:

- server.js
- views/
- - template.ejs
- - layouts/
- - - home.ejs 
- - - login.ejs 

server.js

var data = { 
   layout_view: 'layouts/home'
};
res.render(template, data);

template.ejs

<% include layout_view %>

但是,变量未被过期,只测试变量的名称,而不是值:

  

错误:ENOENT,没有这样的文件或目录   “C:\用户\亚瑟\桌面\节点WWW \ G变\视图\ layout_view.ejs

如何使用<% include %>命令和变量加载视图'views / layouts / home.ejs'?

谢谢大家! :)

2 个答案:

答案 0 :(得分:0)

这是我在Express 4中使用的布局(使用ejs测试):

/*
   Usage:
     Set a global/default layout with:
        app.set('view layout', 'bar');
     Set a layout per-render (overrides global layout) with:
        res.render('foo', { layout: 'bar' });
     Or disable a layout if a global layout is set with:
        res.render('foo', { layout: false });
     If no layout is provided using either of the above methods,
     then the view will be rendered as-is like normal.

     Inside your layout, the variable `body` holds the rendered partial/child view.

   Installation:
     Call `mpResponse();` before doing `require('express');` in your application.
*/

function mpResponse() {
  var expressResponse = require('express/lib/response'),
      expressResRender = expressResponse.render;
  expressResponse.render = function(view, options, fn) {
    options = options || {};
    var self = this,
        req = this.req,
        app = req.app,
        layout,
        cb;

    // support callback function as second arg
    if (typeof options === 'function')
      fn = options, options = {};

    // merge res.locals
    options._locals = self.locals;

    // default callback to respond
    fn = fn || function(err, str) {
      if (err) return req.next(err);
      self.send(str);
    };

    if (typeof options.layout === 'string')
      layout = options.layout;
    else if (options.layout !== false
             && typeof app.get('view layout') === 'string')
      layout = app.get('view layout');

    if (layout) {
      cb = function(err, str) {
        if (err) return req.next(err);
        options.body = str;
        expressResRender.call(self, layout, options, fn);
      };
    } else
      cb = fn;

    // render
    app.render(view, options, cb);
  };
}

答案 1 :(得分:0)

Ben Fortune解决了评论:

EJS上尚未提供的功能,因此更新文件 ejs.js lib / ejs.js (ligne~155)

旧代码

  if (0 == js.trim().indexOf('include')) {
    var name = js.trim().slice(7).trim();
    if (!filename) throw new Error('filename option is required for includes');
    var path = resolveInclude(name, filename);
    include = read(path, 'utf8');
    include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug });
    buf.push("' + (function(){" + include + "})() + '");
    js = '';
  }

新代码

  if (0 == js.trim().indexOf('include')) {
    var name = js.trim().slice(7).trim();
    if (!filename) throw new Error('filename option is required for includes');
    // If it is not path, but variable name (Added)
    var resolvedObj = null;
    var objName = name.split(".");
    if (objName) {
       resolvedObj = options;
       for (var idx=0; idx<objName.length; idx++) {
           resolvedObj = resolvedObj[objName[idx]];
           if ( ! resolvedObj) {break;}
       }
    }

    if(resolvedObj)
       var path = resolveInclude(resolvedObj, filename);
    else
       var path = resolveInclude(name, filename);
    include = read(path, 'utf8');
    include = exports.parse(include, options); // Added transfer whole options
    buf += "' + (function(){" + include + "})() + '";
    js = '';
  }

<强>来源