1. 路由概述
路由:
简单来说,路由是根据不同的url地址展示不同的内容或页面。
- 一个路由就是一个映射关系(key:value)
- key为路径,value可能是function或者component
并且路由这个概念最早是出现在后端的,因为早期的网页都是服务端渲染的,比如:JSP,PHP,ASP等语言,都是直接返回渲染好的html给客户端显示。
1.1 后端路由
在web开发早期的年代里,前端的功能远不如现在强大,一直是后端路由占据主导地址。
无论是jsp,还是php、asp,用户能通过URL访问到的页面,大多是通过后端路由匹配之后再返回给浏览器的。
用户请求的url导航到具体的html页面;每跳转到不同的URL,都是重新访问服务端,然后服务端返回页面,页面也可以是服务端获取数据,然后和模板组合,返回HTML;也可以是直接返回模板HTML,然后由前端js再去请求数据,使用前端模板和数据进行组合,生成想要的HTML。
在后端,路由映射表中就是不同的URL地址与不同的html + css + 后端数据 之间的映射。
- 理解:value是function,用来处理客户端提交的请求。
- 注册路由:
router.get(path,function(req,res)); - 工作过程:当服务器接收到一个请求时,根据请求路径找到匹配的路由,调用路由中的函数来处理请求,返回响应数据。
1.2 前端路由
前端路由是后来发展到SPA(单页应用)时才出现的概念。
- 前端路由把不同路由对应不同的内容或页面的任务交给前端来做。
- 浏览器端路由,value是component,用于展示页面内容。
- 注册路由:
<Route path="/test" component={Test}> - 工作过程:当浏览器的path变为 /test时,当前路由组件就会变为Test组件
前端路由的优点:
- 从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。
- 在某些场合中,用ajax请求,可以让页面无刷新,页面变了但url没有变化,用户就不能复制到想要的地址,用前端路由做单页面网页就很好的解决了这个问题。
前端路由的缺点: 使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存。
2. SPA
- 单页web应用 SPA(single page web
application),就是单页面应用,就是目前前端开发最常见的一种,整个网站由一个html页面构成。 - 三大框架Angular Vue React都是SPA。
- 整个应用只有一个完整的页面。
- 点击页面中的链接不会刷新页面,只会做页面的局部更新。
- 数据都需要通过ajax请求获取,并在前端异步展现。
3. 前端路由两种模式
从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下):
- 记录当前页面的状态 (保存或分享当前页的url,再次打开该url时,网页还是保存或分享时的状态)。
- 可以使用浏览器的前进后退功能(如点击后退按钮,可以使页面回到使用ajax更新页面之前的状态,url也回到之前的状态)
作为开发者,实现这两个功能,需要做到:
- 改变 url 且不让浏览器向服务器发出请求
- 检测 url 的变化
- 截获 url 地址,并解析出需要的信息来匹配路由规则
3.1 hash模式
这里的 hash 就是指 url 尾巴后的 # 号以及后面的字符。这里的 # 和 css 里的 # 是一个意思。 hash也称作锚点,本身是用来做页面定位的,可以使对应 id 的元素显示在可视区域内。
由于 hash 值变化不会导致浏览器向服务器发出请求,因此不会刷新页面,从而实现无刷新的效果。 所以在 html5 的 history 出现前,基本都是使用 hash 来实现前端路由。
hash属性: 在当前页面中,可以通过:window.location.hash = 'edit' 来实现改变当前url的hash值,执行上述的hash赋值,页面的url发生改变。 例如:赋值前:http://localhost:3000 赋值后:http://localhost:3000 /#edit。
hashchange事件: hash改变会触发hashchange事件,浏览器的进后退也能对其进行控制。有了监听事件,且改变hash页面不刷新,这样就可以在监听事件的回调函数中,执行我们展示和隐藏不同UI展示的功能,从而实现前端路由。
window.addEventListener('hashchange', function(){
})
此外,要改变页面的hash值,还可以通过 html的<a> 标签 来实现页面跳转:<a href="#edit"></a>
hash 的缺点:
- 搜索引擎对带有hash的页面不友好
- 带有hash的页面难以追踪用户的行为
3.2 history模式
已经有了hash模式了,而且hash能兼容到IE8,history只能兼容到IE10,为什么还需要history呢?
原因:
- hash本身是用来做页面定位的,如果用来做路由的话,原来的锚点功能就不能用了。
- hash的传参是基于url的,如果需要传递复杂的数据,会有体积的限制;而history 模式不仅可以在url里放参数,还可以将数据存放在一个特定的对象中。
history的属性:
- length:返回在会话历史有多少条记录,包含了当前会话页面。如果打开了一个新的tab,那么这个length会加1
- state:保存了popState等事件方法,所传递过来的属性和对象(后面会在pushState和replaceState方法中详细的介绍)
history的方法:
history.back() :返回浏览器会话历史中的上一页,跟浏览器的 回退 按钮功能相同history.forword() :指向浏览器会话历史中的下一页,跟浏览器的 前进 按钮相同history.go(n) :可以跳转到浏览器会话历史中的 指定的某一个记录页,n可为正数或者负数history.pushState(state, title, url) :pushState可以 将给定的数据压入到浏览器会话历史栈中,该方法接受3个参数,对象,title,和一串url,值得注意的是,pushState调用后会改变页面的url,但是不会刷新页面
- state:需要保存的数据,这个数据在触发popstate事件时,可以在event.state里获取
- title:标题,基本没用,一般传 null
- url:设定新的历史记录的 url。新的 url 与当前 url 的 origin 必须是一樣的,否则会抛出错误。url可以是绝对路径,也可以是相对路径。
- 例如: 当前url是 https://www.baidu.com/a/,执行 history.pushState(null, null, ‘./qq/’),则变成 https://www.baidu.com/a/qq/,执行 history.pushState(null, null, ‘/qq/’),则变成 https://www.baidu.com/qq/
history.replaceState(state, title, url) :replaceState 将当前的会话页面的url替换成指定的数据,replaceState后也会改变当前页面的url,但是也不会刷新页面。
history的优点:
history的缺点:
- 兼容性不如hash
- 需要后端做相应的配置,否则访问子页面回出现404错误。
|