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.hashvar path = hash.substring(1)switch (path) {case '/':showHome()breakcase '/users':showUsersList()breakdefault: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.pathnameswitch (path) {case '/':showHome()breakcase '/users':showUsersList()breakdefault:show404NotFound()}
}

但是这种方法只能捕获前进或后退事件,无法捕获pushState和replaceState,一种最简单的解决方法是替换pushState方法,例如:

var pushState = history.pushState
history.pushState = function() {pushState.apply(history, arguments)// emit a event or just run a callbackemitEventOrRunCallback()
}

不过,最好的方法还是使用实现好的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,来区别对待这两种情况。

转载于:https://www.cnblogs.com/chris-oil/p/8359390.html

[转] 理解Web路由相关推荐

  1. 使用Aura.Router在PHP中进行Web路由

    Everyone is interested in SEO-friendly, REST-style URLs. Apache can do URL routing via mod_rewrite r ...

  2. 《jQuery与JavaScript入门经典》——第 1 章 动态Web编程简介 1.1理解Web服务器浏览器范式...

    本节书摘来自异步社区<jQuery与JavaScript入门经典>一书中的第1章,第1.1节,作者:[美]Brad Dayley著,更多章节内容可以访问云栖社区"异步社区&quo ...

  3. 理解web项目中的VO,DTO,DO,PO

    理解web项目中的VO,DTO,DO,PO 想起第一次实习的时候被嫌弃VO,DTO,DO,PO不分 vo DO DTO PO 想起第一次实习的时候被嫌弃VO,DTO,DO,PO不分 所以他们到底是什么 ...

  4. 深入理解Flask路由(2)- werkzeug 路由系统

    本系列共三篇文章: 深入理解Flask路由的实现机制 深入理解Flask路由(2)- werkzeug 路由系统 深入理解Flask路由 (3) - 动态 url 及转换器 上一篇我们说到:Flask ...

  5. 深入理解WEB请求过程

    随着web2.0时代的到来,互联网的网络架构已经从传统的C/S架构转变成更加方便快捷的B/S架构,B/S架构大大简化了用户使用网络应用的难度,带来了以下两方面的好处: 1.客户端使用统一的浏览器.由于 ...

  6. 全连接层的输入和输出_理解Web应用程序的本质,网络数据流处理与基础网络连接...

    前言 前面一篇文章,我从整个应用程序的整体以及跟运行环境的关系简单聊了一下我们现在常用的Spring框架的设计基础和原则,其中主要是控制反转和依赖注入,以及容器化编程等概念. 这里我不想去复述这些概念 ...

  7. 理解koa-router 路由一般使用

    阅读目录 一:理解koa-router一般的路由 二:理解koa-router命名路由 三:理解koa-router多个中间件使用 四:理解koa-router嵌套路由 五:分割路由文件 回到顶部 一 ...

  8. 如何理解 Web API

    什么是web API? web API 控制器.路由 测试  Web  API  什么是web API ? 简单说,API是接口,访问程序的某一个功能或者数据,实现移动端和客户端的程序之间的数据交互: ...

  9. MVC简单实现插件Demo-从底层理解MVC路由匹配浏览器请求的URL

    今天实现了在mvc平台下自定义插件,虽然功能比较简单,但是通过对反射的运用,更加明白了为什么我们在浏览器上输入友好的url时,mvc会智能的帮我们找到我们想要查找的页面呢?mvc在底层又是怎样实现的呢 ...

最新文章

  1. 如何向数据库添加时同时返回ID
  2. 用DOS命令来运行Java代码
  3. lnmp下配置虚拟主机
  4. python基础(文件、异常、模块、类、对象)
  5. 上拉加载更多后台数据_微信小程序端操作云数据库
  6. java编程有什么独特之处?
  7. jQuery的内容选择器和属性
  8. java修改cdm_Java™ ORM框架CDM教程 增删改查(四)
  9. 自动基线校正 python_红外光谱的
  10. 数字电子技术基础-阎石老师版本-学习记录
  11. 缺少所需的CD/DVD驱动器设备驱动程序
  12. STK10与MATLAB互联
  13. 瀚海星云BBS python脚本登陆
  14. 大一新生HTML期末作业,网页制作作业——明星介绍易烊千玺网站HTML+CSS
  15. wps思维导图聚焦模式是灰色不能用的解决方案
  16. 计算机专业毕业答辩问代码吗,计算机专业毕业论文答辩技巧
  17. 微信中那种卡片形式的图文链接是如何制作的
  18. 一级造价工程师(安装)- 计量笔记 - 第四章第二节热力设备工程
  19. ABC: Always Be Coding
  20. 维基解密网店被封,呼吁全球抵制Coinbase

热门文章

  1. 点击DIV显示改变边框颜色
  2. A brief introduction to complex analysis
  3. java.lang.NoSuchMethodError: net.sf.jsqlparser.statement.update.Update.getTable()Lnet/sf/jsqlparser/
  4. IDC:英国脱欧对本国IT支出带来3大潜在影响
  5. Python Leetcode(507.完美数)
  6. 拷贝PDF中文字出现英文乱码的问题
  7. 【Antdv】input type=number去掉上下箭头、提示文字、鼠标滚轮
  8. shell 循环语句
  9. linux 对应 网口_linux 查看网口类型
  10. Upload 上传:图片上传