【问题标题】:How to configure dynamic routes with express.js如何使用 express.js 配置动态路由
【发布时间】:2014-10-26 16:45:17
【问题描述】:

我有一个如下所示的 route.js:

module.exports = function(app) {

  app.get('/tip', function(req, res) {
    res.render("tip");
  });

  app.get('/article', function(req, res) {
   res.render("article");
  });

  app.get('/article1', function(req, res) {
   res.render("article1");
  });

  app.get('/article2', function(req, res) {
   res.render("article2");
  });

  app.get('/article3', function(req, res) {
   res.render("article3");
  });

  app.get('/modules/:name', function(req, res) {
    var name = req.params.name;
    res.render('modules/' + name);
  });

  app.get('/modules/esaver/:name', function(req, res) {
    var name = req.params.name;
    res.render('modules/esaver/' + name);
  });

};

考虑到我有超过 200 条不同的路线要创建,我最终会得到“article1”、“article2”等内容

我的 app.js 是这样的:

var express = require('express')
  ,http = require('http')
  ,fs = require('fs')
  ,path = require('path');

var app = express();

html_templates = __dirname + '/html_templates';

app.set('views', html_templates + '/views');
app.set('view engine', 'jade');

app.use('/Core', express.static(__dirname + '/Core'));


app.listen(3000, function () {
 console.log("express has started on port 3000");
});

require('./html_templates/controller/routes.js')(app);

有没有动态的方法来创建这个?

【问题讨论】:

    标签: javascript node.js express


    【解决方案1】:

    我会为/modules/:name做同样的事情

    app.get('/article/:id', function(req , res){
      res.render('article' + req.params.id);
    });
    

    从休息的角度来看会更有意义。

    如果您因任何特定原因无法做到这一点,您可能想要执行以下操作:

    var articlesEndpoints = ['/article2', '/article3'];
    articlesEndpoints.forEach(function(name) {
      app.get(name, function(req, res) {
        res.render(name);
      });
    });
    

    这是你的意思吗?

    【讨论】:

    • 是的,我正在寻找类似的东西,但我收到一个错误:错误:无法在视图目录“C:\.....(我使用过foreach)
    • 您确定name 是您所期望的吗?您可能想要记录它并查看它是否存在。
    • @wasiim_dev 如果您的视图位于相对于您的 Express 代码所在位置的子目录 views 中,您需要在代码顶部附近添加 app.set('views', __dirname + '/views');。默认情况下,Express 会查找相对于当前工作目录的路径。
    • 是的,我确认它是名称 - console.log 给出 -> /article、/article1 等
    • 收到您发布的错误的完整路径是什么?
    【解决方案2】:

    终于搞定了..

    如果我得到了文章 1、文章 2 等:

    app.get('/:name(article|article2|article3)?', function(req, res) {
        var name = req.params.name;
        res.render(name);
    });
    

    在我得到多级 url 的情况下,我创建了一个自定义函数:

    function geturl(url) {
    
      app.get('/' + url + '/' + ':name', function(req, res){
        var name = req.params.name;
        res.render(url + '/' + name);
      });
    
    };
    

    【讨论】:

    • 没有 ?在路线的尽头,有什么意义吗?
    • @AdamF ? 使 req.params.name:name 可选。例如上述路径匹配 '/' 与空 :name 和 '/article2' 但不匹配 /abc
    • 你可能会发现这个在线Express Route Tester很有用。
    【解决方案3】:

    有很多方法可以实现动态快速路由。这很大程度上取决于你在项目中实现的结构,这里我举一个动态路由的例子,希望对你有用。

    RouterService.js

    module.exports = (function(myCustomRoutes) {
       let express = require('express');
       let router  = express.Router();
       let methods = Object.keys(myCustomRoutes); // getting methods ('get', 'post'... etc)
       let routesMethod = null;
       let url = null;
    
       for(i in methods) {
          routesMethod = Object.keys(myCustomRoutes[methods[i]]);
          for(j in routesMethod) {
             url = '/' + routesMethod[j];
             url += '/:' + myCustomRoutes[methods[i]][routesMethod[j]].params.join('/:');console.log(url);
             router[methods[i]](url, myCustomRoutes[methods[i]][routesMethod[j]].controller);
          }
       }
    
       return router;
    })();
    

    CustomRoutes.js

    module.exports = (function() {
        let routes = {get: {}, post: {}};
        let routerService = require('./RouterService');
    
        // GET:  /dynamic1
        routes.get.dynamic1 = {
           params: [],
           controller: function(req, res, next) {
               res.send('route 1');
           }
        };
    
        // GET:  /dynamic2/:param1
        routes.get.dynamic2 = {
           params: [':param1'],
           controller: function(req, res, next) {
               res.send('route 2');
           }
        };
        // POST: /dynamic3/:param1/:param1
        routes.post.dynamic3 = {
           params: ['param1', 'param2'],
           controller: function(req, res, next) {
              res.send('route 3');
           }
        };
    
        /*
        *  Export a router with paths
        *  GET:  /dynamic1
        *  GET:  /dynamic2/:param1
        *  POST: /dynamic3/:param1/:param1
        **/
        return routerService(routes);
    })();
    

    app.js

    let express = require('express');
    let app = express();
    
    
    /*
     *  Option 1
     *  GET:  /dynamic1
     *  GET:  /dynamic2/:param1
     *  POST: /dynamic3/:param1/:param1
     **/
     app.use(require('CustomRoutes')());
    
    
    /*
     *  Option 2
     *  GET:  /api/v1/dynamic1
     *  GET:  /api/v1/dynamic2/:param1
     *  POST: /api/v1/dynamic3/:param1/:param1
     **/
     app.use('/api/v1', require('CustomRoutes')());
    

    【讨论】:

    • 对象实例化大括号 () 不应该出现在 routerservice 函数上,这会导致在函数中执行 Object.keys 时出现 NRE
    【解决方案4】:

    这是我在控制哪些 API 允许访问哪些方法时创建动态 API 所做的。要从现在开始维护 API,您只需编辑 API 数组即可。

    const APIs = [
        {
            route: 'order',
            methods: ['get', 'post']
        },
        {
            route: 'item',
            methods: ['get']
        },
    ]
    APIs.forEach(api => {
        api.methods.forEach(method => {
            app[method]('/' + api.route, (req, res) => require('./routes/' + api.route)[method](req, res))
        })
    })
    

    【讨论】:

      【解决方案5】:

      这里有几个其他的解决方案:

      app.get(^\/article(\d{1,3})?\/?$, function(req, res, next) {
        var n;
        if (req.params[0])
          n = parseInt(req.params[0], 10);
      
        if (!n || (n > 0 && n < 900))
          res.render('article' + (n ? n : ''));
        else
          next();
      });
      

      或使用app.all 作为第一个解决方案或使用通用中间件:

      app.use(function(req, res, next) {
        var m = ^\/article(\d{1,3})?\/?$.exec(req.url);
        if (m) {
          var n;
          if (m[0])
            n = parseInt(m[0], 10);
      
          if (!n || (n > 0 && n < 900))
            return res.render('article' + (n ? n : ''));
        }
        next(); 
      });
      

      【讨论】:

      • 这可以部分解决问题。如果我有而不是文章——(小费、食谱等),这里有 100 多种可能性。我想要一些可以用作“/”之后的*项的通用
      【解决方案6】:

      我创建了一个名为:jadewalker 的新模块。它将自动创建路由器代码。

      我们可以简单地将jadewalker 评论添加到您的jadepug 文件中。

      //- jadewalker=/b,/b/:id
      doctype html
      html
       title b.jade
      body
        p b.jade
        p params: #{params.id}
      

      并将这个模块添加到我们的app。就是这样。

      var app = require('koa')()
      var router = require('koa-router')();
      router = require('jadewalker')(router, path.join(__dirname, 'views'));
      app.use(router.routes());
      

      我们可以通过 URL http://localhost:3000/b/abc 访问我们的翡翠文件。 (^∀^)

      【讨论】:

        【解决方案7】:

        这是我的项目的工作

        routesPath = path.join(__dirname, 'routes');
        
        fs.readdirSync(routesPath).forEach(function(file) {
          require(routesPath + '/' + file)(app);
        });
        

        【讨论】:

          猜你喜欢
          • 2016-05-28
          • 2013-05-22
          • 1970-01-01
          • 1970-01-01
          • 2013-07-26
          • 1970-01-01
          • 1970-01-01
          • 2015-12-17
          相关资源
          最近更新 更多