Подтвердить что ты не робот

Несколько путей просмотра на Node.js + Express

Я пишу CMS на Node.js с помощью Express Framework. На моей CMS у меня есть несколько модулей для пользователей, страниц и т.д.

Я хочу, чтобы каждый модуль имел свои файлы в отдельной папке, , включая файлы вида. Кто-нибудь знает, как я могу это достичь?

Я использую swig как мой механизм шаблонов, но я могу заменить его на что-то другое, если это поможет.

4b9b3361

Ответ 1

Последнее обновление

Функция папок с несколькими представлениями поддерживается каркасом, так как Express 4.10

Просто передайте массив мест в свойство views, например.

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

Экспресс 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)
    };
}

Вы активируете новую логику, вызывая функцию выше и передавая выражение как параметр, а затем вы сможете указать массив представлений конфигурации:

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 будет 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);
};

Я не тестировал его, он все равно очень хлопот, к несчастью эта функция была отброшена назад: https://github.com/visionmedia/express/pull/1186

ОБНОВЛЕНИЕ 2

Эта функция была добавлена ​​в Express 4.10, так как следующий запрос на pull был объединен: https://github.com/strongloop/express/pull/2320

Ответ 2

В дополнение к ответу @user85461, часть запроса на просмотр не работает для меня. Что я сделал: удалил материал пути и переместил все это в модуль, который я мог бы потребовать, 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 "View", чтобы сделать тот же трюк поиска, что и решение @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

Однако вы можете поместить все файлы вида в папку "view", но отделить каждый модуль от его собственных папок внутри папки "view". Итак, структура выглядит примерно так:

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

Установите файлы вида, как обычно:

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

И когда рендер для каждого модуля включает имя модуля:

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

или даже имя подмодуля:

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

Это решение также работает в express перед версией 4.x,

Ответ 5

Установить глобус 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')