react-router的BrowserHistory 和 HashHistory 的區別,如何解決使用BrowserHistory 引起的訪問路徑問題


 

 

 

一,使用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。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM