React | hashRouter和browserRouter的区别

react-router的工作方式

顶层是一个Router组件,在组件树中散落着许多Route组件

顶层的Router组件负责分析监听URL的变化,在此之下Route组件可以直接读取这些信息

1
2
3
4
5
6
7
8
9
10
11
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { HashRouter } from 'react-router-dom';
import './index.css';
import App from './App';

ReactDOM.render((
/*HashRouter监听着App这个组件的url的变化*/
<HashRouter><App /></HashRouter>
), document.getElementById('root'));

路由需要实现的三个功能:

  1. 当浏览器地址变化时,切换页面;
  2. 点击浏览器后退、前进按钮,网页内容发送变化;
  3. 刷新浏览器,页面加载内容对应当前路由对应的地址;

在单页面web网页中,单纯的浏览器地址改变,网页不会重载,如单纯的hash值改变,网页是不会变化的,因此我们的路由需要监听事件,并利用js实现动态改变网页

  • hash模式(onhashchange):监听浏览器地址hash值变化,并执行相应的js切换【前进后退等】
  • history模式(popstate):利用H5 history API实现url地址改变,网页内容改变

BrowserRouter和HashRouter的区别和特点

BrowserRouter

window.history对象表示的是当前窗口得浏览历史,当发生改变时,只会改变路径,不会刷新页面

History对象就是一个堆栈

方法:

  • History.back:移动上一个网址,等同于浏览器的后退
  • History.forward:移动到下一个网址,等同于浏览器前进
  • History.go(n):接受一个参数,以当前网页为基准,来进行跳转,默认history.go(0),刷新当前页面
  • History.pushState():往history堆栈中添加一条记录,不会刷新页面,只会导致history对象变化,地址栏发生变化
  • History.replaceState():替换当前history堆栈中最上层的记录,不会刷新页面,只会导致history对象变化,地址栏发生变化

每当history对象发生变化,就会触发popstate事件:window.addEventListener(‘popstate’, function(){});

[只调用pushState或者replaceState是不会触发该事件的,只有调用back forward go才会触发该事件]

HashRouter

使用window.location.hash属性和window.onhashchange事件,可以监听浏览器hash值的变化,去执行相应的js切换路由

hash路由实现原理:

  1. hash指的是地址#号以及后面的字符,称为散列值
  2. 散列值不会随着请求发送到服务端的,所以改变hash,不会重新加载页面
  3. 监听onhashchange事件,hash改变时,可以通过window.location.hash来获取和设置hash值
  4. location.hash值得变化直接反应在浏览器得地址栏

总结

底层原理不一样

  • BrowserRouter:利用HTML5 history的API,有低版本兼容性问题
  • HashRouter:利用URL的哈希值,window.location.hash

地址栏表现形式不一样

  • BrowserRouter路径:localhost:3000/demo/a
  • HashRouter路径:localhost:3000/#/demo/a

刷新后对路由state参数的影响

  • BrowserRouter没有任何影响,因为state保存在history对象中
  • HashRouter刷新后会导致路由state参数丢失