这关乎于Nodejs的express路由规则(http://hm4123660.iteye.com/blog/2195035)
express 封装了多种 http 请求方式,我们主要只使用 get和post,可以使用 app.all 获取所以请求方式,回调函数有两个参数分别是 req 和 res,代表请求信息和响应信息。
- req.query
: 处理 get 请求
- req.params
: 处理 /:xxx 形式的 get 请求
- req.body
: 处理 post 请求
- req.param()
: 可以处理 get 和 post 请求,但查找优先级由高到低为req.params→req.body→req.query
例如:
获取表达post的参数
var username=req.body.name;//获取post参数 var password=req.body.password;
获取get参数
访问URL:http://localhost:3000/test?id=110&password=120
获取代码:
app.get(‘/test‘,function(req,res){ res.send("id: "+req.query.id+" password: "+req.query.password); })
结果:
一. *通配URL
例如:
app.get(‘/test/*‘,function(req,res){ res.send(req.originalUrl);//req.originalUrl获取当前URL });
*号可以通配URL为localhost:3000/test/.......的URL
运行结果:
二. /:id的占位标识符URL
例如:
app.get(‘/test/:userid‘,function(req,res){ res.send("userid: "+req.params.userid);//req.params.userid获取userid的值 });
运行结果:
不能继续使用/
三.next()权限控制转移
express的路由控制有个next()功能,在定义了多个路由的时候,使用next对匹配的url会按顺序执行,
如果不使用next进行权限转移,只会执行第一个满足的路由规则。
<span class="token comment">next() 函数用于将当前控制权转交给下一步处理,如果给 next() 传递一个参数时,表示出错信息</span>
例如:
app.get(‘/test/*‘,function(req,res,next){ //res.send("userid:");//要进行转移,不要响应客户端 req.temp="给你控制权"; next();//把权限转移到下一个路由 }); app.get(‘/test/next‘,function(req,res){ res.send("content: "+req.temp); })
访问URL:http://localhost:3000/test/next满足这两个路由规则
运行结果:
next()一般用来编写中间件
- 中间件一般不直接对客户端进行响应,而是对请求进行一些预处理,再传递下去;
- 中间件一般会在路由处理之前执行;
比如:
// 检查用户是否登录中间件,所有需要登录权限的页面都使用此中间件
function checkLogin (req, res, next) {
if (req.session.user) {
next();//检验到用户已登入,转移权限阁下一个路由
} else {
res.redirect(‘/‘);//否则,页面重定位,不执行下面路由
}
}
满足了通配符*和next()两个条件(需要传入),就可以使得二级路由获得权限了。
app.get(‘/*‘, function (req, res, next) { // 就是不能有这一句 // res.sendFile(__dirname + ‘/../dist/index.html‘); // 上面这一句其实是无关紧要的,并不需要它就可以访问第一个路由 req.temp="给你控制权"; next(); }); app.get(‘/test‘,function(req,res){ res.send("content: "+req.temp); })
静态目录其实已经在app.use的时候指定了
app.use(‘/‘, express.static(__dirname + ‘/../dist‘)); app.use(‘/scripts‘, express.static(__dirname + ‘/../node_modules‘));
res.sendFile之后next或者在获取了控制权的下一级路由中写这一句,都会报Forbidden的。
这是单纯node中路由的跳转,在angular2中,不会去加载另一个html文件,还是要用angular自己的方式实现,参看 Angular2 路由教程 3 - 子模块以及异步加载(https://gold.xitu.io/entry/58523aa91b69e6006c7e63ac)
如果像一般的starter那样把todo相关的路由定义在一个文件中,然后在app的路由定义中把所有路由合并到一起。todo.routes.ts
的内容如下:
// 省略import
export const TodoRoutes: Route[] = [
{
path: ‘todo‘,
canActivateChild: [MyTodoGuard],
children: [
{ path: ‘list‘, component: TodoListComponent, resolve: { todos: MyTodoResolver } },
{ path: ‘detail/:id‘, component: TodoDetailComponent, canDeactivate: [ CanLeaveTodoDetailGuard ] }
]
}
];
然后在app.routes.ts
中定义一个路由模块:
const routes: Routes = [
{ path: ‘‘, redirectTo: ‘/home‘, pathMatch: ‘full‘ },
{ path: ‘home‘, component: HomeComponent },
...TodoRoutes // 这里就是将TodoRoutes列表里的内容合并到routes
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule { }
最后,在AppModule里面引入这个路由模块。
这种方式实现的路由无法实现子模块的延时加载,要实现延时加载,首先要将todo模块的路由修改成子路由模块,也就是要修改todo.routes.ts
:
// 省略import
export const TodoRoutes: Route[] = [
{
path: ‘todo‘,
canActivateChild: [MyTodoGuard],
children: [
{ path: ‘list‘, component: TodoListComponent, resolve: { todos: MyTodoResolver } },
{ path: ‘detail/:id‘, component: TodoDetailComponent, canDeactivate: [ CanLeaveTodoDetailGuard ] }
]
}
];
// 通过下面的方式定义了一个子路由模块
@NgModule({
imports: [ RouterModule.forChild(TodoRoutes) ],
exports: [ RouterModule ]
})
export class TodoRoutingModule { }
这里定义了一个子路由模块,TodoRoutingModule
,它使用RouterModule.forChild(TodoRoutes)
来创建。跟整个App的路由模块比较的话,主路由模块使用RouterModule.forRoot(routes)
来定义。
定义好了子路由模块,在子模块里面引入它既可:
// 省略import
@NgModule({
imports: [CommonModule, FormsModule, TodoRoutingModule ],
declarations: [TodoListComponent, TodoDetailComponent, TodoItemComponent],
providers: [TodoService, MyTodoResolver, MyTodoGuard, CanLeaveTodoDetailGuard]
})
export class TodoModule {}
这样就定义好了一个子模块。当用户打开/todo/list
或/todo/detail/*
时,这个子模块里面的相关页面就会展示,它也不会跟其他模块有任何交互。也就是说,进入和离开这个子模块,都是通过路由跳转实现。这个子模块也是完全独立的,可以独立开发,也可以很容易就用到其他应用里面。