原文地址:http://syaning.com/2017/01/10...?认识Web路由一、什么是路由在Web开发过程中,经常会遇到“路由”这个概念。那么,路由到底是什么?简单来说,路由就是URL到函数的映射。2.router和route的区别route就是路由,将一个url路径映射到一个函数,例如:/users->getAllUsers()/users/count->getUsersCount()这是两条路由,当访问/当访问用户时,会执行getAllUsers()函数;当访问/users/count时,将执行getUsersCount()函数。路由器可以理解为一个容器,或者说是一种机制,它管理着一组路由。简单的说,route只是将url和function进行映射,收到一个url后,在route映射表中查找对应的function,这个过程由router来处理。一句话,就是“路由器将你路由到一条路线”。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在匹配路由的过程中,不仅会根据url进行匹配,还会根据请求的method来判断是否匹配。比如上面的例子,如果通过POST方式访问/users,就会找不到正确的路由。4.客户端路由对于客户端(通常是浏览器)来说,路由映射功能通常会进行一些DOM显示和隐藏操作。这样访问不同的路径时,就会显示不同的页面组件。客户端路由最常见的实现方式如下:Hash-basedandHistoryAPI(1)Hash-based我们知道URL中#和后面的部分都是哈希。例如:consturl=require('url')vara=url.parse('http://example.com/a/b/#/foo/bar')console.log(a.hash)//=>#/foo/barhash只是client的一种状态,也就是说,当向server发送请求时,hash部分是不会发送的。简单的路由可以通过监听window对象的hashChange事件来实现。例如:window.onhashchange=function(){varhash=window.location.hashvarpath=hash.substring(1)switch(path){case'/':showHome()breakcase'/users':showUsersList()breakdefault:show404NotFound()}}(2)在HistoryAPI的基础上,HTML5HistoryAPI可以直接改变当前的URL而无需刷新页面。详细用法可以参考:操作浏览器历史使用HTML5HistoryAPI我们可以通过监听window对象的popstate事件实现简单的路由:window.onpopstate=function(){varpath=window.location.pathnameswitch(path){case'/':showHome()breakcase'/users':showUsersList()breakdefault:show404NotFound()}}但是这个方法只能捕获forward或者backward事件,不能捕获pushState和replaceState,其中之一最简单的解决方案方法是替换pushState方法,例如:varpushState=history.pushStatehistory.pushState=function(){pushState.apply(history,arguments)//emitaeventorjustrunacallbackemitEventOrRunCallback()}然而,最好的方法是使用一个实现良好的历史库。(3)两种实现方式的比较总的来说,Hash-basedrouting具有更好的兼容性;基于历史API的路由更加直观和正式。但是有一个很大的区别,基于Hash的路由不需要对服务器进行任何改动,而基于HistoryAPI的路由需要对服务器进行一些修改。我们来详细分析一下。假设服务器只有以下文件(index.html引用了script.js):/-|-index.html|-script.js基于哈希的路径是:http://example.com/http://example.com/#/foobar基于HistoryAPI的路径为: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错误。因此,如果使用基于HistoryAPI的路由,需要修改server端,使访问/foobar时返回index.html文件,这样浏览器加载页面和脚本后,路由跳转就可以了被执行。5、动态路由上面提到的例子都是静态路由,即路径是固定的。但是有时候我们需要在路径中传入参数,比如获取某个用户的信息,我们不可能为每个用户创建一个路由,而是通过抓取路径中的参数来实现(比如作为用户ID)。例如在Express中:app.get('/user/:id',(req,res,next)=>{//......})在Flask中:@app.route('/user/
