【问题标题】:Look up layouts and include files on multiple paths in express/ejs在 express/ejs 中查找布局并包含多个路径上的文件
【发布时间】:2023-03-08 05:23:02
【问题描述】:

我正在使用 ejs 作为模板引擎构建基于 express 的节点应用程序。

为了支持网站的不同外观,我想将文件放在名为 base 的文件夹中,其中包含 vanilla 内容和每个样式/主题/客户端的叠加层。我希望系统首先在叠加层中查找文件,并且只有在未找到时才使用基础中的文件。

对于像图像和 css 文件这样的静态内容,这会使用静态中间件两次,首先用于叠加层,然后用于基础。

我想对通过 ejs 呈现的模板做同样的事情。我发现:

Multiple View paths on Node.js + Express

只要我调用简单的 ejs 视图,该线程中提供的 BananaAcids 答案几乎对我有用。如果我想使用布局或包含它,它会分解为覆盖视图,因为基本目录现在是覆盖的,并且不再找到与基本目录未更改的布局。

下面是一个简化的例子。

文件base/layouts/root.ejs:

<!DOCTYPE html>
<html lang="en">
  <body>
    <!-- Main content of pages using this layout goes here -->
    <%- body %>
  </body>
</html>

文件库/index.ejs:

<% layout('layouts/root') -%>
<p>
    A page in base using the root layout
</p>

文件覆盖/index.ejs:

<% layout('layouts/root') -%>
<p>
    Totally different page in the overlay.
</p>

使用 BananaAcids 方法并将两个路径设置为 view-sources express/ejs 现在可以正确地将 overlay/index.ejs 定位为要渲染的视图,但由于我没有覆盖 layouts/root,因此它失败了,因为生成的文件 overlay/layouts/ root.ejs 不存在。

有没有办法将我的方式进一步修补到 ejs 中,以便我可以帮助它在 base/layout/root.ejs 中找到这个文件?

感谢您阅读本文以及您为此花费的任何脑力周期。

【问题讨论】:

    标签: node.js express ejs


    【解决方案1】:

    这是我使用猴子补丁 Express (4.x) 添加布局支持的方法:

    /*
       Usage:
         Set a global/default layout with:
            app.set('view layout', 'foo');
         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);
      };
    }
    

    【讨论】:

      【解决方案2】:

      我修补了 EJS 以支持 Express v.4.10 中添加的多视图文件夹功能。当前有一个待处理的拉取请求,您可以在此处找到:https://github.com/mde/ejs/pull/120。如果您的项目仍然需要此解决方案,您可以将我的 fork 包含到您的 package.json 中作为 EJS 替代品:

      { ... "dependencies": { "ejs": "git://github.com/MarcelloDiSimone/ejs.git#feature/multi-views" } }

      ..或者你加一个拉取请求,希望它会很快被接受。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-03
        • 2012-10-18
        • 2012-12-16
        • 1970-01-01
        • 1970-01-01
        • 2015-09-10
        • 2016-11-16
        • 2018-06-04
        相关资源
        最近更新 更多