1. 什么是路由
路由(routing)就是通過互聯(lián)的網(wǎng)絡(luò)把信息從源地址傳輸?shù)侥康牡刂返幕顒?dòng)。
以上是中文維基百科對(duì)路由的解釋。通俗的來講,把一個(gè)地方的信息傳輸?shù)剿肴サ哪康牡氐倪^程,就叫路由。
2. 用代碼解釋路由
需求:頁(yè)面上有2個(gè)按鈕,分別是登陸和注冊(cè),點(diǎn)擊登陸按鈕,就切換到對(duì)應(yīng)的登陸界面,點(diǎn)擊注冊(cè)按鈕,就切換到對(duì)應(yīng)的注冊(cè)界面。
示例代碼:
function Box1(){
return <div className="box">登陸</div>
}
function Box2(){
return <div className="box">注冊(cè)</div>
}
function App() {
let [n, setN] = useState(0)
return (
<div className="App">
<div>
<button onClick={()=> setN(0)}>登陸</button>
<button onClick={()=> setN(1)}>注冊(cè)</button>
</div>
<div>
{ n % 2 === 0 ? <Box1 />:<Box2 />}
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
這個(gè)其實(shí)就是路由的雛形了,每個(gè)頁(yè)面對(duì)應(yīng)著一個(gè)組件,然后在不同狀態(tài)下去切換 。
3. 新增的需求
提出需求:在分享該頁(yè)面出去時(shí),用戶直接到達(dá)注冊(cè)頁(yè)面。(以上示例代碼的首頁(yè)是登陸界面)
3.1 修改 url 中的 hash 值
url 中 #(hash) 的含義
URL 的hash部分,指的是#后的部分
window.location.hash可讀取或?qū)懭?hash值
function Box1() {
return <div className="box">登錄</div>;
}
function Box2() {
return <div className="box">注冊(cè)</div>;
}
function App() {
//獲取當(dāng)前的hash值
let hash = window.location.hash;
let initUI = hash === "#signup" ? "注冊(cè)" : "登錄";
let [ui, setUI] = useState(initUI);
//切換頁(yè)面時(shí),改hash
let onClickLogin = () => {
setUI("登錄");
window.location.hash = "login";
};
let onClickSignUp = () => {
setUI("注冊(cè)");
window.location.hash = "signup";
};
return (
<div className="App">
<div>
<button onClick={onClickLogin}>登錄</button>
<button onClick={onClickSignUp}>注冊(cè)</button>
</div>
<div>{ui === "登錄" ? <Box1 /> : <Box2 />}</div>
</div>
);
}
#signup : 注冊(cè), 空或 #login: 登錄。
不同的界面對(duì)應(yīng)不同的字符串(hash),把用戶送往其想到達(dá)的目的地,就是路由。
3.2 除了 hash 還能用什么
但是,地址欄上有這個(gè) “#” 符號(hào)不太好看,能不能變好看點(diǎn)?
- 直接修改
pathname,但會(huì)刷新頁(yè)面
不用
window.location.hash = "login";
而用
window.location.pathname = "/login";
我只是想切換個(gè)tab,頁(yè)面就整個(gè)刷新了啊
- 使用
window.history.pushState()
可以不刷新頁(yè)面而改變pathname。
window.history.pushState(null, '', '/login')
function App() {
let path = window.location.pathname;
let initUI = path === "/signup" ? "注冊(cè)" : "登錄";
console.log(initUI);
let [ui, setUI] = useState(initUI);
let onClickLogin = () => {
setUI("登錄");
window.history.pushState(null, "", "/login");
};
let onClickSignUp = () => {
setUI("注冊(cè)");
window.history.pushState(null, "", "/signup");
};
return (
<div className="App">
<div>
<button onClick={onClickLogin}>登錄</button>
<button onClick={onClickSignUp}>注冊(cè)</button>
</div>
<div>{ui === "登錄" ? <Box1 /> : <Box2 />}</div>
</div>
);
}
3.3 三種方式的區(qū)別
-
window.location.hash(保險(xiǎn)辦法)
可讓url變化,同時(shí)不刷新頁(yè)面 -
window.location.pathname
會(huì)刷新頁(yè)面,別用 -
window.history.pushState( , , )(想好看用這個(gè))
不刷新頁(yè)面,并改變pathname
但 建議:只有后端將所有路徑都指向首頁(yè)時(shí),才使用這個(gè)API。
4. React Router
上面的代碼存在著重大缺陷:
- 如果
path過多,代碼就要寫很多if ... else - 路由有無限個(gè),無法寫
暫不考慮使用正則表達(dá)式。使用 React Router 來解決這些問題吧 : )
React Router,保持 UI 和 URL同步。
4.1 安裝 React Router
使用命令行:
npm install react-router-dom
注意:
react-router: 實(shí)現(xiàn)了路由的核心功能。
react-router-dom: 基于react-router,加入了在瀏覽器運(yùn)行環(huán)境下的一些功能。
寫網(wǎng)站的時(shí)候一般引入 react-router-dom 就可以了
4.2 使用 React Router
建議查看的官網(wǎng):react-router
import { BrowserRouter as Router, Switch, Link, Route } from "react-router-dom";
function Home(){
return <div className="box">首頁(yè)</div>
}
function Login(){
return <div className="box">登錄</div>
}
function SignUp(){
return <div className="box">注冊(cè)</div>
}
function App(){
return(
<div className="app">
<Router>
<div className="nav">
<Link to="/" className="link">首頁(yè)</Link> | <Link to="/login" className="link">登錄</Link> | <Link to="/signup" className="link">注冊(cè)</Link>
</div>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/login">
<Login />
</Route>
<Route path="/signup">
<SignUp />
</Route>
</Switch>
</Router>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'));