目前常見的路由分爲兩種,HashRouter
和BrowserRouter
html
hash
路由的方式主要是經過改變hash
值來改變url
,由於只是改變hash
,因此並不會觸發頁面刷新,很適合用在單頁應用局部更新,window
提供監聽hashChange
方法來監聽hash值的改變去更新咱們的單頁react
window.addEventListener('hashchange', function(e) {
console.log('hashchange', e)
// 更新頁面
})
複製代碼
history是h5新出的api,讓咱們能夠在改變url而不刷新頁面,主要的幾個api是:git
History.back()
: 返回瀏覽器會話歷史中的上一頁,跟瀏覽器的回退按鈕功能相同github
History.forward()
:指向瀏覽器會話歷史中的下一頁,跟瀏覽器的前進按鈕相同。api
History.go()
: 能夠跳轉到瀏覽器會話歷史中的指定的某一個記錄頁。瀏覽器
History.pushState()
:pushState能夠將給定的數據壓入到瀏覽器會話歷史棧中,該方法接收3個參數,對象,title和一串url。pushState後會改變當前頁面url,可是不會伴隨着刷新。bash
History.replaceState()
:replaceState將當前的會話頁面的url替換成指定的數據,replaceState後也會改變當前頁面的url,可是也不會刷新頁面。ide
以上只是實現改變url
不刷新頁面,咱們還須要監聽用戶前進後退的變化。popstate
是history的一個監聽事件,能夠監聽history的變化學習
好了,基本上就是這個原理ui
實現部分主要是利用react
的context api
來存儲路由信息,子組件根據context
值去渲染,代碼是由hook
實現,不瞭解的,看以前,學習一下React Hook,下面咱們來實現一下BrowserRouter
import React, { useState } from "react";
let set; // 保存setUrl,由於監聽事件我們值加入一次,因此放外面
function popstate(e) {
set(window.location.pathname);
}
// 建立context
export const RouterContext = React.createContext(window.location.pathname);
export default function({ children }) {
const [url, setUrl] = useState(window.location.pathname);
set = setUrl;
window.addEventListener("popstate", popstate);
const router = {
history: {
push: function(url, state, title) {
window.history.pushState(state, title, url);
setUrl(url);
},
replace: function(url, state, title) {
window.history.replaceState(state, title, url);
setUrl(url);
},
// 下面也須要嵌入setUrl,暫不處理
go: window.history.go,
goBack: window.history.back,
goForward: window.history.forward,
length: window.history.length
},
url: url
};
return (
<RouterContext.Provider value={router}>{children}</RouterContext.Provider>
);
}
複製代碼
import React, { useContext } from "react";
import { RouterContext } from "./BrowserRouter";
function Route({ component, path }) {
// 獲取context
const { history, url } = useContext(RouterContext);
const match = {
path,
url
};
const Component = component;
return url === path && <Component history={history} match={match} />;
}
export default Route;
複製代碼
import React, { useContext } from "react";
import { RouterContext } from "./BrowserRouter";
import styled from "styled-components";
const A = styled.a`
text-decoration: none;
padding: 5px;
`;
function Link({ children, to }) {
const { history } = useContext(RouterContext);
const onClick = e => {
e.preventDefault();
history.push(to);
};
return (
<A href={to} onClick={onClick}>
{children}
</A>
);
}
export default Link;
複製代碼
查看Github源碼 其實很簡單的一個東西,瞭解原理很容易實現,看了這篇文章,你也能夠試着去實現一下HashRouter
.