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(),效果以下:css

 

 

 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(),效果以下:html

 

 

3. 經過上面的對比, 能夠發現

createBrowserHistory() 和 createHashHistory() 的區別體如今 打開頁面的路徑上:react

createBrowserHistory: http://localhost:8084/secondwebpack

createHashHistory: http://localhost:8084/#/secondgit

還有一個 createMemoryHistorygithub

——如今來看看官方介紹:web

  • 「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: 未使用,不作介紹cookie

 

 

二,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。

相關文章
相關標籤/搜索