明白路由

原文地点:http://syaning.com/2017/01/10…

明白Web路由

1.什么是路由

在Web开辟历程当中,经常会碰到『路由』的观点。那末,究竟什么是路由?简朴来讲,路由就是URL到函数的映照。

2.router和route的区分

route就是一条路由,它将一个URL途径和一个函数举行映照,比方:

/users        ->  getAllUsers()
/users/count  ->  getUsersCount()

这就是两条路由,当接见/users的时刻,会实行getAllUsers()函数;当接见/users/count的时刻,会实行getUsersCount()函数。

而router能够明白为一个容器,或许说一种机制,它管理了一组route。简朴来讲,route只是举行了URL和函数的映照,而在当接收到一个URL以后,去路由映照表中查找响应的函数,这个历程是由router来处置惩罚的。一句话归纳综合就是 “The router routes you to a route“。

3.服务器端路由

关于服务器来讲,当接收到客户端发来的HTTP要求,会依据要求的URL,来找到响应的映照函数,然后实行该函数,并将函数的返回值发送给客户端。关于最简朴的静态资本服务器,能够以为,一切URL的映照函数就是一个文件读取操纵。关于动态资本,映照函数多是一个数据库读取操纵,也多是举行一些数据的处置惩罚,等等。

以Express为例,

app.get('/', (req, res) => {
  res.sendFile('index')
})

app.get('/users', (req, res) => {
  db.queryAllUsers()
    .then(data => res.send(data))
})

这里定义了两条路由:

当接见/的时刻,会返回index页面
当接见/users的时刻,会从数据库中掏出一切用户数据并返回
不仅仅是URL

在router婚配route的历程当中,不仅会依据URL来婚配,还会依据要求的要领来看是不是婚配。比方上面的例子,假如经由过程POST要领来接见/users,就会找不到准确的路由。

4.客户端路由

关于客户端(一般为浏览器)来讲,路由的映照函数一般是举行一些DOM的显现和隐蔽操纵。如许,当接见差别的途径的时刻,会显现差别的页面组件。客户端路由最常见的有以下两种完成计划:

基于Hash
基于History API
(1) 基于Hash

我们晓得,URL中#及其背面的部份为hash。比方:

const url = require('url')
var a = url.parse('http://example.com/a/b/#/foo/bar')
console.log(a.hash)
// => #/foo/bar

hash仅仅是客户端的一个状况,也就是说,当向服务器发要求的时刻,hash部份并不会发过去。

经由过程监听window对象的hashChange事宜,能够完成简朴的路由。比方:

window.onhashchange = function() {
  var hash = window.location.hash
  var path = hash.substring(1)

  switch (path) {
    case '/':
      showHome()
      break
    case '/users':
      showUsersList()
      break
    default:
      show404NotFound()
  }
}

(2) 基于History API

经由过程HTML5 History API能够在不革新页面的状况下,直接转变当前URL。细致用法能够参考:

Manipulating the browser history
Using the HTML5 History API

我们能够经由过程监听window对象的popstate事宜,来完成简朴的路由:

window.onpopstate = function() {
  var path = window.location.pathname

  switch (path) {
    case '/':
      showHome()
      break
    case '/users':
      showUsersList()
      break
    default:
      show404NotFound()
  }
}

然则这类要领只能捕捉行进或退却事宜,没法捕捉pushState和replaceState,一种最简朴的解决要领是替代pushState要领,比方:

var pushState = history.pushState
history.pushState = function() {
  pushState.apply(history, arguments)

  // emit a event or just run a callback
  emitEventOrRunCallback()
}

不过,最好的要领照样运用完成好的history库。

(3) 两种完成的比较

总的来讲,基于Hash的路由,兼容性更好;基于History API的路由,越发直观和正式。

然则,有一点很大的区分是,基于Hash的路由不须要对服务器做修改,基于History API的路由须要对服务器做一些革新。下面来细致分析。

假定服务器只要以下文件(script.js被index.html所援用):

/-
 |- index.html
 |- script.js

基于Hash的途径有:

http://example.com/
http://example.com/#/foobar

基于History API的途径有:

http://example.com/
http://example.com/foobar

当直接接见 http://example.com/ 的时刻,二者的行动是一致的,都是返回了index.html文件。

当从http://example.com/跳转到http://example.com/#/foobar或许http://example.com/foobar的时刻,也都是一般的,由于此时已加载了页面以及剧本文件,所以路由跳转一般。

当直接接见http://example.com/#/foobar的时刻,实际上向服务器提议的要求是http://example.com/,因而会起首加载页面及剧本文件,接下来剧本实行路由跳转,一切一般。

当直接接见http://example.com/foobar的时刻,实际上向服务器提议的要求也是http://example.com/foobar,但是服务器端只能婚配/而没法婚配/foobar,因而会涌现404毛病。

因而假如运用了基于History API的路由,须要革新服务器端,使得接见/foobar的时刻也能返回index.html文件,如许当浏览器加载了页面及剧本以后,就可以举行路由跳转了。

5.动态路由

上面提到的例子都是静态路由,也就是说,途径都是牢固的。然则有时刻我们须要在途径中传入参数,比方猎取某个用户的信息,我们不可能为每一个用户建立一条路由,而是在经由过程捕捉途径中的参数(比方用户id)来完成。

比方在Express中:

app.get('/user/:id', (req, res, next) => {
  // ... ...
})

在Flask中:

@app.route('/user/<user_id>')
def get_user_info(user_id):
    pass

6.严厉路由

在许多状况下,会碰到/foobar和/foobar/的状况,它们看起来异常相似,但是实际上有所区分,详细的行动也是视服务器设置而定。

在Flask的文档中,提到,末端有斜线的途径,类比于文件体系的一个目次;末端没有斜线的途径,类比于一个文件。因而接见/foobar的时刻,可能会重定向到/foobar/,而反过来则不会。

假如运用的是Express,默许这二者是一样的,也能够经由过程app.set来设置strict routing,来区分对待这两种状况。

    原文作者:specialCoder
    原文地址: https://segmentfault.com/a/1190000008175640
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞