2012-07-03 5 views
34

J'écris un CMS sur Node.js avec Express Framework. Sur mon CMS j'ai plusieurs modules pour les utilisateurs, pages, etc.Plusieurs chemins d'accès sur Node.js + Express

Je veux que chaque module aura ses fichiers sur dossier séparé, y compris les fichiers de vue. Quelqu'un sait comment je peux y arriver?

J'utilise swig comme mon moteur de modèle mais je peux le remplacer par quelque chose d'autre si cela peut aider.

+1

Quelque chose comme ceci fonctionnerait pour vous? http://stackoverflow.com/questions/9470466/node-express-js-overriding-where-to-look-for-the-views-folder-for-each-reque –

+0

http://stackoverflow.com/questions/ 36374424/mean-app-with-admin-panneau-et-client-panel? Answertab = actif # tab-top –

Répondre

35

Dernière mise à jour

Les multiples dossiers fonction d'affichage est pris en charge par le cadre depuis express 4.10

Il suffit de passer un tableau d'emplacements à la propriété views, comme ainsi.

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

Express 2.0

Pour autant que je sais exprimer ne prend pas en charge plusieurs chemins de vue ou namespaces au moment (comme le middleware statique faire)

Mais vous pouvez modifier la recherche logique vous afin que cela fonctionne comme vous le souhaitez, par exemple:

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) 
    }; 
} 

vous permettra à la nouvelle logique par Callin g la fonction ci-dessus et passer expriment comme paramètre, et vous serez en mesure de spécifier un tableau de vues à la configuration:

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

Ou, si vous préférez, vous pouvez patcher le cadre directement (mise à jour le view.js fichier à l'intérieur)

Cela devrait travail express 2.x, pas sûr que ce sera avec la nouvelle version (3.x)

MISE à JOUR

Serve la solution ci-dessus ne fonctionnera pas dans 3.x express depuis express.view serait non définie

Une autre solution possible sera de proxy la réponse .rendre la fonction et définir la configuration du dossier de vues jusqu'à ce qu'il obtienne un match:

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); 
}; 

Je ne l'ai pas testé, il se sent très hacky pour moi en tout cas, malheureusement cette fonction a été repoussée à nouveau: https://github.com/visionmedia/express/pull/1186

MISE à JOUR 2

Cette fonctionnalité a été ajoutée express 4.10, étant donné que la demande de traction suivante a été fusionné: https://github.com/strongloop/express/pull/2320

+0

Il n'est pas question de l'implémenter dans 3.x donc votre fonction devrait fonctionner dans la nouvelle version. – Pickels

+0

Oui, il semble que oui, mais certaines (nombreuses?) API de 3.x ont changé, et je pense que cela a été refactorisé, il ne semble pas qu'elles aient trop changé le fichier view.js ces derniers temps: https://github.com/ visionmedia/express/commits/master/lib/view.js Cela fonctionnera probablement, je vais le tester quand j'ai du temps libre – BFil

+0

Je l'ai fait dans un module qui fonctionne pour Express 4.x. https://www.npmjs.org/package/multi-views –

5

Voici une solution pour Express 3.x. Les patchs de singe expriment l'objet "View" de 3.x pour faire le même tour de recherche que la solution @ ShadowCloud ci-dessus. Malheureusement, la recherche de chemin pour l'objet View est moins propre, puisque 3.x ne l'expose pas à express - vous devez donc creuser dans les entrailles de 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(); 
11

En plus de la réponse @ user85461, la partie de vue requise n'a pas fonctionné pour moi. Ce que je l'ai fait: retiré les choses de chemin et déplacé tout à un module que je pourrais avoir besoin, patch.ViewEnableMultiFolders.js (Fonctionne avec express en cours):

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; 

et utilisé:

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

Vous pouvez cependant placer tous les fichiers de vue dans le dossier 'view', mais séparer la vue de chaque module dans ses propres dossiers dans le dossier 'view'. Ainsi, la structure est quelque chose comme ceci:

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

Définissez l'affichage des fichiers comme d'habitude:

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

Et rendre pour chaque module, inclure le nom du module:

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

ou même nom du sous-module:

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

Cette solution fonctionne aussi en mode express avant la version 4.x,