【问题标题】:Multiple View paths on Node.js + ExpressNode.js + Express 上的多个视图路径
【发布时间】:2012-07-04 03:31:38
【问题描述】:

我正在 Node.js 和 Express Framework 上编写 CMS。在我的 CMS 上,我有几个用于用户、页面等的模块。

我希望每个模块都有自己的文件在单独的文件夹包括视图文件。 有谁知道我怎样才能做到这一点?

我使用 swig 作为我的模板引擎,但如果有帮助,我可以将其替换为其他东西。

【问题讨论】:

标签: node.js express


【解决方案1】:

上次更新

框架从 Express 4.10 开始支持多视图文件夹功能

只需将一组位置传递给views 属性,就像这样。

app.set('views', [__dirname + '/viewsFolder1', __dirname + '/viewsFolder2']);

Express 2.0

据我所知,express 目前不支持多个视图路径或命名空间(就像静态中间件一样)

但您可以自己修改查找逻辑,使其按您想要的方式工作,例如:

function enableMultipleViewFolders(express) {
    // proxy function to the default view lookup
    var lookupProxy = express.view.lookup;

    express.view.lookup = function (view, options) {
        if (options.root instanceof Array) {
            // clones the options object
            var opts = {};
            for (var key in options) opts[key] = options[key];

            // loops through the paths and tries to match the view
            var matchedView = null,
                roots = opts.root;
            for (var i=0; i<roots.length; i++) {
                opts.root = roots[i];
                matchedView = lookupProxy.call(this, view, opts);
                if (matchedView.exists) break;
            }
            return matchedView;
        }

        return lookupProxy.call(express.view, view, options)
    };
}

您将通过调用上面的函数并将 express 作为参数来启用新逻辑,然后您将能够为配置指定一组视图:

var express = require('express');
enableMultipleViewFolders(express);
app.set('views', [__dirname + '/viewsFolder1', __dirname + '/viewsFolder2']);

或者,如果您愿意,可以直接修补框架(更新其中的 view.js 文件)

这应该适用于 Express 2.x,不确定是否适用于新版本 (3.x)

更新

不幸的是,上述解决方案在 Express 3.x 中不起作用,因为 express.view 将是 undefined

另一种可能的解决方案是代理 response.render 函数并设置视图文件夹配置直到匹配:

var renderProxy = express.response.render;
express.render = function(){
    app.set('views', 'path/to/custom/views');
    try {
        return renderProxy.apply(this, arguments);
    }
    catch (e) {}
    app.set('views', 'path/to/default/views');       
    return renderProxy.apply(this, arguments);
};

我没有测试过,反正我觉得很hacky,不幸的是这个功能又被推迟了: https://github.com/visionmedia/express/pull/1186

更新 2

此功能已在 Express 4.10 中添加,因为以下拉取请求已合并: https://github.com/strongloop/express/pull/2320

【讨论】:

  • 没有任何关于在 3.x 中实现这一点的讨论,所以你的函数应该在新版本中工作。
  • 是的,看起来是这样,但是 3.x 中的一些(很多?)API 发生了变化,我认为它已被重构,最近他们似乎并没有太多地更改 view.js 文件:@ 987654323@应该可以了,有空我去测试一下
  • 我已经把它做成了一个适用于 Express 4.x 的模块。 npmjs.org/package/multi-views
  • @Feng - 从docs 中似乎并不明显。它只说views 设置为单个目录。能否请您指出一个地方和文档或支持多个目录的代码?
  • @VagmiMudumbai 刚刚注意到这是几天前添加的,登陆 4.10 而不是 4.x github.com/strongloop/express/pull/2320
【解决方案2】:

除了@user85461 的回答,require view 部分对我不起作用。 我做了什么:删除路径内容并将其全部移动到我可能需要的模块中, patch.ViewEnableMultiFolders.js(适用于当前快递):

function ViewEnableMultiFolders(app) {
    // Monkey-patch express to accept multiple paths for looking up views.
    // this path may change depending on your setup.
    var lookup_proxy = app.get('view').prototype.lookup;

    app.get('view').prototype.lookup = function(viewName) {
        var context, match;
        if (this.root instanceof Array) {
            for (var i = 0; i < this.root.length; i++) {
                context = {root: this.root[i]};
                match = lookup_proxy.call(context, viewName);
                if (match) {
                    return match;
                }
            }
            return null;
        }
        return lookup_proxy.call(this, viewName);
    };
}

module.exports.ViewEnableMultiFolders = ViewEnableMultiFolders;

并使用:

var Patch = require('patch.ViewEnableMultiFolders.js');
Patch.ViewEnableMultiFolders(app);
app.set('views', ['./htdocs/views', '/htdocs/tpls']);

【讨论】:

    【解决方案3】:

    这是 Express 3.x 的解决方案。它猴子补丁表达了 3.x 的“视图”对象,以执行与上述@ShadowCloud 解决方案相同的查找技巧。不幸的是,View 对象的路径查找不太干净,因为 3.x 没有将它暴露给express——所以你必须深入了解 node_modules。

    function enable_multiple_view_folders() {
        // Monkey-patch express to accept multiple paths for looking up views.
        // this path may change depending on your setup.
        var View = require("./node_modules/express/lib/view"),
            lookup_proxy = View.prototype.lookup;
    
        View.prototype.lookup = function(viewName) {
            var context, match;
            if (this.root instanceof Array) {
                for (var i = 0; i < this.root.length; i++) {
                    context = {root: this.root[i]};
                    match = lookup_proxy.call(context, viewName);
                    if (match) {
                        return match;
                    }
                }
                return null;
            }
            return lookup_proxy.call(this, viewName);
        };
    }
    
    enable_multiple_view_folders();
    

    【讨论】:

      【解决方案4】:

      但是,您可以将所有视图文件放在“视图”文件夹中,但将每个模块的视图分隔到“视图”文件夹中自己的文件夹中。所以,结构是这样的:

      views  
      --moduleA    
      --moduleB  
      ----submoduleB1  
      ----submoduleB2  
      --moduleC  
      

      像往常一样设置视图文件:

      app.set('views', './views');
      

      并且在为每个模块渲染时,包括模块的名称:

      res.render('moduleA/index', ...);
      

      甚至是子模块的名称:

      res.render('moduleB/submoduleB1/index', ...);
      

      此解决方案也适用于版本 4.x 之前的 express,

      【讨论】:

        【解决方案5】:

        安装 glob npm install glob

        如果您有一个类似于以下内容的views 目录:

        views
        ├── 404.ejs
        ├── home.ejs
        ├── includes
        │   ├── header.ejs
        │   └── footer.ejs
        ├── post
        │   ├── create.ejs
        │   └── edit.ejs
        └── profile.ejs
        
        

        您可以使用此 glob 函数返回 views 目录中的子目录数组(添加 path.substring 以删除结尾的 /

        let viewPaths = glob.sync('views/**/').map(path => {
            return path.substring(0, path.length - 1)
        })
        
        
        console.log(viewPaths)
        >> ['views', 'views/post', 'views/includes']
        

        所以现在你可以设置

        app.set('views', viewPaths)
        

        现在你可以使用

        res.render('404')
        res.render('home')
        res.render('post/edit')
        res.render('post/create')
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-14
          • 1970-01-01
          • 2012-07-07
          相关资源
          最近更新 更多