一,使用createBrowserHistory 和 createHashHistory 的 区别体现

1. 使用createBrowserHistory ()

// 使用createBrowserHistory的代码
import React from 'react';
import { Router, Route, Switch} from 'react-router-dom';
import { createHashHistory, createMemoryHistory, createBrowserHistory} from 'history'; import First from './container/First';
import Second from './container/Second';
import Third from './container/Third';
import Fourth from './container/Fourth'; const router = (props) => {
return (
<Router history={createBrowserHistory()}>
<Switch>
<Route exact path={"/"} component={First} />
<Route exact path={"/first"} component={First} />
<Route exact path={"/second"} component={Second} />
<Route exact path={"/third"} component={Third} />
<Route exact path={"/fourth"} component={Fourth} />
</Switch>
</Router>
)
}
export default router;

使用createBrowserHistory(),效果如下:

 2. 使用createHashHistory()

//使用createHashHistory
const router = (props) => {
return (
<Router history={createHashHistory()}>
<Switch>
<Route exact path={"/"} component={First} />
<Route exact path={"/first"} component={First} />
<Route exact path={"/second"} component={Second} />
<Route exact path={"/third"} component={Third} />
<Route exact path={"/fourth"} component={Fourth} />
</Switch>
</Router>
)
}
export default router;

使用createHashHistory(),效果如下:

3. 通过上面的对比, 可以发现

createBrowserHistory() 和 createHashHistory() 的区别体现在 打开页面的路径上:

createBrowserHistory: http://localhost:8084/second

createHashHistory: http://localhost:8084/#/second

还有一个 createMemoryHistory

——现在来看看官方介绍:

  • “browser history” - A DOM-specific implementation, useful in web browsers that support the HTML5 history API
  • “hash history” - A DOM-specific implementation for legacy web browsers
  • “memory history” - An in-memory history implementation, useful in testing and non-DOM environments like React Native

browserHistory: 是使用浏览器中的 History API 来处理 URL(使用 React Router 推荐的 history)

hashHistory: 是使用 URL 中的 hash(#)部分去创建路由

memoryHistory: 未使用,不做介绍

二,browserHistory 和 hashHistory 的优缺点比较

1. 先看看官方推荐的 browserHistory 

browserHistory 是使用 React-Router 的应用推荐的 history方案。它使用浏览器中的 History API 用于处理 URL,创建一个像example.com/list/123这样真实的 URL 。

(摘自http://react-guide.github.io/react-router-cn/docs/guides/basics/Histories.html)

因为是使用真实的浏览器history,就像HTML网页间的跳转一样,和浏览器的操作配合完美(浏览器自带的“后退”,“前进”,“刷新” 按钮,浏览器会记录浏览history)

另外:此处需要解释一下单页面应用(SPA)和多页面应用(MPA):

1)多页面模式(MPA  Multi-page Application): 
    多页面跳转需要刷新所有资源,每个公共资源(js、css等)需选择性重新加载
    页面跳转:使用window.location.href = "./index.html"进行页面间的跳转;
    数据传递:可以使用path?account="123"&password=""路径携带数据传递的方式,或者localstorage、cookie等存储方式

2)单页面模式(SPA  Single-page Application): 
    只有一个Web页面的应用,是一种从Web服务器加载的富客户端,单页面跳转仅刷新局部资源 ,公共资源(js、css等)仅需加载一次
    页面跳转:使用js中的append/remove或者show/hide的方式来进行页面内容的更换;
    数据传递:可通过全局变量或者参数传递,进行相关数据交互

多页面模式,就是多个HTML页面之间的操作,浏览器会通过自身的history处理好页面间的操作,

单页面模式,对于浏览器来说只有一个HTML页面,任何操作都在同一个页面内,浏览器无法监控到页面跳转(实际只是内容改变,路径没变)

在单页面模式下使用browserHistory 的问题是:只有一个真实的html页面,是无法体现出html页面之间跳转的效果的

这时就需要使用服务器配合,模拟出多个HTML页面,从而实现浏览器真实的页面跳转效果

2. 问题展示:

——在webpack 的 本地服务器模式下webpack-dev-server插件模拟的本地服务器 )

未开启historyApiFallback:

// 本地服务器 webpack-dev-server插件,开发中server,便于开发,可以热加载
devServer: {
contentBase: './dist', //默认本地服务器所在的根目录
//historyApiFallback: true,
inline: true, //源文件改变时刷新页面
port: 8084 //端口号,默认8080
},

开启historyApiFallback:

// 本地服务器 webpack-dev-server插件,开发中server,便于开发,可以热加载
devServer: {
contentBase: './dist', //默认本地服务器所在的根目录
historyApiFallback: true, //开启
inline: true, //源文件改变时刷新页面
port: 8084 //端口号,默认8080
},

由此可见webpack-dev-server 中 设置 historyApiFallback 可以解决browserHistory 的问题

historyApiFallback 功能:

当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html

三,那么,非开发模式(打出来的包)怎么办??

方法一: 使用服务器进行相关配置,配合browserHistory进行使用

可以参考这篇文章: https://www.thinktxt.com/react/2017/02/26/react-router-browserHistory-refresh-404-solution.html

其实,就是通过服务器(无论Nginx,还是Node都可以)在浏览器方法该目录下(比如dist文件夹)的文件时,都返回 index.html,

比如访问  example.com/list/123 路径,

  1. 但是服务器下没有这个文件可供访问,
  2. 所以就需要通过设置服务器,当浏览器访问不存在的页面时,都给索引到 index.html
  3. 在index.html 我们的browserHistory 才能派上用场

方法二: 使用HashRouter,虽然路径 http://localhost:8084/#/second 多个‘#’,虽然项目内跳转页面可能会有问题。。。

如果有服务器端的动态支持,建议使用 BrowserRouter,否则建议使用 HashRouter。

react-router的BrowserHistory 和 HashHistory 的区别,如何解决使用BrowserHistory 引起的访问路径问题的更多相关文章

  1. React+React Router+React-Transition-Group实现页面左右滑动+滚动位置记忆

    2018年12月17日更新: 修复在qq浏览器下执行pop跳转时页面错位问题 本文的代码已封装为npm包发布:react-slide-animation-router 在React Router中,想 ...

  2. [转] React Router 使用教程

    PS:react-route就是一个决定生成什么父子关系的组件,一般和layout结合起来,保证layout不行,内部的子html进行跳转 你会发现,它不是一个库,也不是一个框架,而是一个庞大的体系. ...

  3. React Router基础使用

    React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单 ...

  4. React Router 使用教程

    一.基本用法 React Router 安装命令如下. $ npm install -S react-router 使用时,路由器Router就是React的一个组件. import { Router ...

  5. React Router教程

    React Router教程 React项目的可用的路由库是React-Router,当然这也是官方支持的.它也分为: react-router 核心组件 react-router-dom 应用于浏览 ...

  6. React Router API文档

    React Router API文档 一.<BrowserRouter> 使用HTML5历史记录API(pushState,replaceState和popstate事件)的<Rou ...

  7. React Router基础教程

    React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单 ...

  8. React Router学习

    React Router教程 本教程引用马伦老师的的教程 React项目的可用的路由库是React-Router,当然这也是官方支持的.它也分为: react-router 核心组件 react-ro ...

  9. [Web 前端] 你不知道的 React Router 4

    cp from https://segmentfault.com/a/1190000010718620 几个月前,React Router 4 发布,我能清晰地感觉到来自 Twitter 大家对新版本 ...

随机推荐

  1. Cesium原理篇:GroundPrimitive【转】

    今天来看看GroundPrimitive,选择GroundPrimitive有三个目的:1 了解GroundPrimitive和Primitive的区别和关系 2 createGeometry的特殊处 ...

  2. windows7平台android studio新建Android项目,报错

    Failed to install the following Android SDK packages as some licences have not been accepted. platfo ...

  3. Xamarin.FormsShell基础教程(8)Shell的模版构成

    Xamarin.FormsShell基础教程(8)Shell的模版构成 Shell模版创建的页面包含内容页.标签栏.侧滑菜单.搜索框四部分.下面依次介绍这几个部分. 内容页:内容页就是为用户呈现内容的 ...

  4. ImportError: this is MySQLdb version (1, 2, 5, 'final', 1), but _mysql is version (1, 4, 4, 'final', 0)

    (flask-demo) ➜ flask-demo git:(master) ✗ pip install mysqlclient==1.2.5 DEPRECATION: Python 2.7 will ...

  5. Spark SQL里concat_ws和collect_set的作用

    concat_ws: 用指定的字符连接字符串 例如: 连接字符串: concat_ws("_", field1, field2),输出结果将会是:“field1_field2”. ...

  6. Cassandra3在Centos7下启动失败解决办法

    Centos7 安装Cassandra启动过程提示失败,查看结果如下所示: [root@xx ~]# systemctl status cassandra ● cassandra.service - ...

  7. 在条件判断中使用 all() / any()

    在条件判断中使用 all() / any() all() 和 any() 两个函数非常适合在条件判断中使用.这两个函数接受一个可迭代对象,返回一个布尔值,其中: all(seq):仅当 seq 中所有 ...

  8. Ubuntu 安装docker CE以及harbor

    Docker CE安装 系统建议版本:Ubuntu 16.04 官方安装文档连接:https://docs.docker.com/install/linux/docker-ce/ubuntu/#pre ...

  9. JobStorage.Current property value has not been initialized. You must set it before using Hangfire Client or Server API.

    JobStorage.Current property value has not been initialized. You must set it before using Hangfire Cl ...

  10. Node 脚本的调试工具

    2016年,Node 决定将 Chrome 浏览器的"开发者工具"作为官方的调试工具,使得 Node 脚本也可以使用图形界面调试 1.准备 创建目录 D:\nodejs>mk ...