Route Mapper - JavaScript 实现的 Rails Routing 风格的路由系统

2015-01-19 20:41:31 +08:00
 fundon

Route Mapper

JavaScript 实现 (ES6+ 编写)的 Rails Routing 风格的路由系统。
通过它可以生成 routes mapper,借助 routes mapper 可以进行 DIY ,方便、简化路由入口与其他模块的整合开发。

基本上实现算法都是参照 actionpack/lib/action_dispatch/routing 及好文 Rails 路由系统源码探索
使用 JavaScript ES6+ 进行编写开发(跟上时代步伐……)。

例子(源自 rails new blog 生成路由模板)

let routeMapper = new RouteMapper();
routeMapper.draw((m) => {

  // You can have the root of your site routed with "root"
  m.root('welcome#index');

  // /products/233  controller = catalog, action = view
  m.get('products/:id', { to: 'catalog#view' });

  // Example named route that can be invoked with purchase_path(id: product.id)
  // /products/233/purchase === purchase_path(233)
  m.get('products/:id/purchase', { to: 'catalog#purchase', as: 'purchase' });

  // Example resource route (maps HTTP verbs to controller actions automatically):
  m.resources('products');

  // Example resource route with options:
  m.resources('products', () => {
    m.member(() => {
      m.get('short');
      m.post('toggle');
    });

    m.collection(() => {
      m.get('sold');
    });
  });

  // Example resource route with sub-resources:
  m.resources('products', () => {
    m.resources('comments', 'sales');
    m.resource('seller');
  });

  // Example resource route with more complex sub-resources:
  m.resources('products', () => {
    m.resources('comments')
    m.resources('sales', () => {
      m.get('recent', { on: 'collection' });
    });
  });

  // Example resource route with concerns:
  m.concern('toggleable', () => {
    m.post('toggle');
  });
  m.resources('posts', { concerns: 'toggleable' });
  m.resources('photos', { concerns: 'toggleable' });

  // Example resource route within a namespace:
  m.namespace('admin', () => {
    // Directs /admin/products/*
    m.resources('products');
  });

});

结合现有 Node.js 的 web frameworks

Express

import express from 'express';
import RouteMapper from '../..';

let app = express();

let routeMapper = new RouteMapper();
routeMapper.draw((m) => {
  m.root('welcome#index');
  m.resources('photos');
  m.constraints({ subdomain: 'api' }, () => {
    m.namespace('api',  { defaults: { format: 'json' }, path: '/' }, () => {
        m.scope({ module: 'v1' }, () => {
          m.resources('users');
        });
      }
    );
  });
});


app.use(function (req, res, next) {
  res.locals.urlHelpers = routeMapper.urlHelpers;
  next();
});

routeMapper.routes.forEach((r) => {
  r.via.forEach((m) => {
    let controller = r.controller;
    let action = r.action;
    let c = require(__dirname + '/controllers/' + controller + '.js');
    let a;
    if (c && (a = c[action])) {
      if (!Array.isArray(a)) {
        a = [a];
      }
      app[m](r.path, ...a);
    };
  });
});

app.listen(3300);

Koa

import koa from 'koa';
import router from 'koa-router';
import RouteMapper from '../..';

let app = koa();

let routeMapper = new RouteMapper();
routeMapper.draw((m) => {
  m.root('welcome#index');
  m.get('about', { to: 'welcome#about' });
  m.resources('posts', () => {
    m.resources('comments');
  });
  m.scope({ path: '~:username?', module: 'users', as: 'user'}, () => {
    m.root('welcome#index');
  });
});

app.use(function *(next) {
  this.urlHelpers = routeMapper.urlHelpers;
  yield next;
});

app.use(router(app));

routeMapper.routes.forEach((r) => {
  r.via.forEach((m) => {
    let controller = r.controller;
    let action = r.action;
    let c = require(__dirname + '/controllers/' + controller + '.js');
    let a;
    if (c && (a = c[action])) {
      if (!Array.isArray(a)) {
        a = [a];
      }
      app[m](r.path, ...a);
    };
  });
});

app.listen(3300);

其他

Rails 在这些地方的设计确实很棒,Express.js,Koa.js 等 Node.js Web 框虽然 DIY 等能力很强,但总感觉过于松散,每次下手都得对目录结构想一番。
该模块还在不懂的完善中。:)

3196 次点击
所在节点    分享创造
2 条回复
GPU
2015-01-19 23:45:10 +08:00
轮子哦,赞赞
Temo
2015-01-23 14:09:15 +08:00
赞一个!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/163594

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX