概念
在说到
router
的一个概念,我们需要先明白另一个概念, 站点。
- 无论是使用
Vue
,还是React
,开发的单页应用程序,可能只是该站点的一部分(某一个功能块)- 一个单页应用里,可能会划分为多个页面(几乎完全不同的页面效果)(组件)
如果要在单页应用中完成组件的切换,需要实现下面两个功能:
- 根据不同的页面地址,展示不同的组件(核心)
- 完成无刷新的地址切换
我们把实现了以上两个功能的插件,称之为路由,
Vue
官方提供了一个路由的插件——vue-router
React
的话,官方提供了一个核心插件——react-router
, 如果是在dom中的话,那么使用react-router-dom
,如果是native的话,那么使用react-router-native
。这两个库都是基于react-router
进行拓展的,意味着按照任意一个库都会帮我们按照上核心库。
原理
不管是
vue
还是react
的路由,都是有两种模式的:
hash
模式history
模式
地址的组成成分
就随便拿一个地址来分析,如下图:
- 协议名(schema):https
- 主机名(host):csdnnews.blog.csdn.net
- ip地址
- 预设值:localhost
- 域名
- 局域网中电脑名称
- 端口号(port):443
- 如果协议是http,端口号是80,则可以省略端口号
- 如果协议是https,端口号是443,则可以省略端口号
- 路径(path):/article/details/115713578
- 地址参数(search、query):?a=1&b=2
- 附带的数据
- 格式:属性名=属性值&属性名=属性值…
- 哈希(hash、锚点):#maodian
- 附带的数据
Hash Router 哈希路由
根据url
地址中的哈希值来确定显示的组件,在#后面出现的任何字符,都会被浏览器解读为位置标识符。这意味着,这些字符都不会被发送到服务器端。因此,hash的变化会使浏览器只会滚动到相应位置,不会重新加载网页。所以#(sharp)
被用来当作锚点,这也是为啥vue中的hash模式不能使用锚点来定位了。每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用"后退"或者“前进”按钮,就可以回到上一个位置。
监听hash 变化
监听hash的变化,浏览器提供了
hashchange
的方法,注册这个方法后就可以监听hash的变化了,并且获取当前hash
的方法是location.hash
// dom加载完成
document.addEventListener('DOMContentLoaded', () => {
alert('hash变化了,当前的hash是:'+location.hash);
})
// hash变化后,就会执行下面的方法
window.addEventListener('hashchange', () => {
alert('hash变化了,当前的hash是:'+location.hash);
})
原因
hash
的变化,不会导致页面刷新
这种模式的兼容性最好,能兼容好久以前的浏览器,但是也有一个
History Router 浏览器历史记录路由
HTML5出现后,新增了
History Api
,从此以后,浏览器拥有了改变路径而不刷新页面的方式。History
表示浏览器的历史记录,它使用栈的方式存储。如果你使用history.pushState('第一个组件',null,'/123')
这个H5 里面的api来改变地址(path)
,浏览器是不会刷新页面的。本质上是监听popstate
事件.
注意:pushState
和replaceState
这两个方法是不会触发popstate
事件的, 如果想要监听他两个的行为,那么直接把这两个方法变异处理一下,类似 vue2中的变异数组方法一样。
document.addEventListener('DOMContentLoaded', () => {
alert('地址发生变化了,当前的path是:' + location.pathname);
})
window.addEventListener('popstate', () => {
alert('地址发生变化了,当前的path是:' + location.pathname);
})
- history.length:获取栈中数据量
- history.pushState:向当前历史记录栈中加入一条新的记录
- 参数1:附加的数据,自定义的数据,可以是任何类型
- 参数2:页面标题,目前大部分浏览器不支持
- 参数3:新的地址
- history.replaceState:将当前指针指向的历史记录,替换为某个记录
- 参数1:附加的数据,自定义的数据,可以是任何类型
- 参数2:页面标题,目前大部分浏览器不支持
- 参数3:新的地址
根据页面的路径决定渲染哪个组件