簡體   English   中英

Node.js + Express上的多個View視圖路徑

[英]Multiple View paths on Node.js + Express

我正在使用Express FrameworkNode.js上編寫CMS。 在我的CMS上,我有幾個用戶,頁面等模塊。

我希望每個模塊都將他的文件放在單獨的文件夾中包括視圖文件 任何人都知道如何實現這一目標?

我正在使用swig作為我的模板引擎但如果有幫助我可以將其替換為其他內容。

最后更新

自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)一起使用

UPDATE

不幸的是,上述解決方案在Express 3.x中不起作用,因為express.view將是未定義的

另一種可能的解決方案是代理response.render函數並設置views文件夾配置,直到獲得匹配:

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

除了@ user85461答案之外,require視圖部分對我不起作用。 我做了什么:刪除路徑的東西,並將其全部移動到我可能需要的模塊,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']);

這是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();

但是,您可以將所有視圖文件放在“視圖”文件夾中,但將每個模塊的視圖分隔到“視圖”文件夾中的自己的文件夾中。 所以,結構是這樣的:

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

像往常一樣設置視圖文件:

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

在為每個模塊渲染時,請包含模塊的名稱:

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

甚至子模塊的名稱:

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

此解決方案也適用於版本4.x之前的快遞,

安裝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')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM