URL的hash
- 前端路由是如何做到URL和组件内容进行映射呢?监听URL的改变
- URL的hash,即锚点(#),本质上是改变window.location的href属性
- 可以通过直接赋值location.hash来改变href,但是页面不发生更新
H5的History
认识React-Router
- React Router6.X版本较之前发生了较大变化
- 目前React Router6.X 已经非常稳定,可放心食用 安装React Router
npm i react-router-dom
Router的基本使用
路由映射
路由配置和跳转
NavLink的使用
代码 :
import React, { PureComponent } from "react";
import { NavLink, Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import "./style.css";
export class App extends PureComponent {
render() {
return (
<div className="app">
<div className="header">
<span>Header</span>
<div className="nav">
{/* <Link to="/home">首页</Link> */}
{/* <Link to="/about">关于</Link> */}
{/* <NavLink to="/home" style={({ isActive }) => ({ color: isActive ? "red" : "" })}>
首页
</NavLink>
<NavLink to="/about" style={({ isActive }) => ({ color: isActive ? "red" : "" })}>
关于
</NavLink> */}
<NavLink to="/home" className={({ isActive }) => (isActive ? "zmClass" : "")}>
首页
</NavLink>
<NavLink to="/about" className={({ isActive }) => (isActive ? "zmClass" : "")}>
关于
</NavLink>
</div>
</div>
<div className="content">
{/* 映射关系:path => Component */}
<Routes>
<Route path="/home" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Routes>
</div>
<div className="footer">Footer</div>
</div>
);
}
}
export default App;
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { HashRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<HashRouter>
<App />
</HashRouter>
</React.StrictMode>
);
自定义样式
.zmClass {
color: aqua;
font-size: 20px;
}
Navigate导航
- Navigate组件被渲染就会跳转到相应的组件页面
import React, { PureComponent } from "react";
import { Navigate } from "react-router-dom";
export class Login extends PureComponent {
constructor() {
super();
this.state = {
isLogin: false,
};
}
login() {
this.setState({
isLogin: true,
});
}
render() {
const { isLogin } = this.state;
return (
<div>
<h1>Login Pages</h1>
{/* 只要出现Navigate页面就会跳转 */}
{!isLogin ? <button onClick={(e) => this.login()}>登录</button> : <Navigate to="/home" />}
</div>
);
}
}
export default Login;
/重定向<Route path="/" element={<Navigate to="/home" />}></Route>
import React, { PureComponent } from "react";
import { NavLink, Navigate, Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import "./style.css";
import Login from "./pages/Login";
export class App extends PureComponent {
render() {
return (
<div className="app">
<div className="header">
<span>Header</span>
<div className="nav">
<NavLink to="/home" className={({ isActive }) => (isActive ? "zmClass" : "")}>
首页
</NavLink>
<NavLink to="/about" className={({ isActive }) => (isActive ? "zmClass" : "")}>
关于
</NavLink>
<NavLink to="/login" className={({ isActive }) => (isActive ? "zmClass" : "")}>
登录
</NavLink>
</div>
</div>
<div className="content">
{/* 映射关系:path => Component */}
<Routes>
<Route path="/" element={<Navigate to="/home" />}></Route>
<Route path="/home" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="/login" element={<Login />}></Route>
</Routes>
</div>
<div className="footer">Footer</div>
</div>
);
}
}
export default App;
NotFound页面配置
<div className="content">
{/* 映射关系:path => Component */}
<Routes>
<Route path="/" element={<Navigate to="/home" />}></Route>
<Route path="/home" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="*" element={<NotFound />}></Route>
</Routes>
</div>
嵌套路由
<Routes>
<Route path="/" element={<Navigate to="/home" />}></Route>
<Route path="/home" element={<Home />}>
{/* 嵌套路由 */}
{/* 匹配到/home需要重定向到二级路由,显示内容 */}
<Route path="/home" element={<HomeRecommend />}></Route>
<Route path="/home/recommend" element={<HomeRecommend />}></Route>
<Route path="/home/ranking" element={<HomeRanking />}></Route>
</Route>
<Route path="/about" element={<About />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="*" element={<NotFound />}></Route>
</Routes>
配置二级路由出口 <Outlet />
import React, { PureComponent } from "react";
import { Link, Outlet } from "react-router-dom";
export class Home extends PureComponent {
render() {
return (
<div>
<h2>Home Pages</h2>
<div className="home-nav">
<Link to="/home/recommend">推荐</Link>
<Link to="/home/ranking">排行榜</Link>
</div>
<div>
{/* 占位的组件,类似router-view */}
<Outlet />
</div>
</div>
);
}
}
export default Home;
自定义(手动)跳转-useNavigate()
函数式组件
import React from "react";
import { NavLink, Navigate, Route, Routes, useNavigate } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import "./style.css";
import Login from "./pages/Login";
import NotFound from "./pages/NotFound";
import HomeRecommend from "./pages/HomeRecommend";
import HomeRanking from "./pages/HomeRanking";
import Category from "./pages/Category";
import Order from "./pages/Order";
export function App() {
// hooks放置到顶层
const navigate = useNavigate();
function navigateTo(path) {
navigate(path);
}
return (
<div className="app">
<div className="header">
<span>Header</span>
<div className="nav">
<NavLink to="/home" className={({ isActive }) => (isActive ? "zmClass" : "")}>
首页
</NavLink>
<NavLink to="/about" className={({ isActive }) => (isActive ? "zmClass" : "")}>
关于
</NavLink>
<NavLink to="/login" className={({ isActive }) => (isActive ? "zmClass" : "")}>
登录
</NavLink>
<button onClick={(e) => navigateTo("/order")}>订单</button>
<button onClick={(e) => navigateTo("/category")}>分类</button>
</div>
</div>
<div className="content">
{/* 映射关系:path => Component */}
<Routes>
<Route path="/" element={<Navigate to="/home" />}></Route>
<Route path="/home" element={<Home />}>
{/* 嵌套路由 */}
<Route path="/home" element={<HomeRecommend />}></Route>
<Route path="/home/recommend" element={<HomeRecommend />}></Route>
<Route path="/home/ranking" element={<HomeRanking />}></Route>
</Route>
<Route path="/about" element={<About />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/category" element={<Category />}></Route>
<Route path="/order" element={<Order />}></Route>
<Route path="*" element={<NotFound />}></Route>
</Routes>
</div>
<div className="footer">Footer</div>
</div>
);
}
export default App;
封装高阶组件,实现在类组件中使用useNavigate()
import { useNavigate } from "react-router-dom";
function withRouter(OriginCpn) {
return (props) => {
const navigate = useNavigate();
const router = { navigate };
return <OriginCpn {...props} router={router} />;
};
}
export default withRouter;
import React, { PureComponent } from "react";
import { NavLink, Navigate, Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import "./style.css";
import Login from "./pages/Login";
import NotFound from "./pages/NotFound";
import HomeRecommend from "./pages/HomeRecommend";
import HomeRanking from "./pages/HomeRanking";
import withRouter from "./hoc/with_router";
import Category from "./pages/Category";
import Order from "./pages/Order";
export class App extends PureComponent {
navigateTo(path) {
console.log("path=> ", path);
// 类组件中使用useNavigate()跳转,报错
const { navigate } = this.props.router;
console.log("666=> ");
navigate(path);
}
render() {
return (
<div className="app">
<div className="header">
<span>Header</span>
<div className="nav">
<NavLink to="/home" className={({ isActive }) => (isActive ? "zmClass" : "")}>
首页
</NavLink>
<NavLink to="/about" className={({ isActive }) => (isActive ? "zmClass" : "")}>
关于
</NavLink>
<NavLink to="/login" className={({ isActive }) => (isActive ? "zmClass" : "")}>
登录
</NavLink>
<button onClick={(e) => this.navigateTo("/order")}>订单</button>
<button onClick={(e) => this.navigateTo("/category")}>分类</button>
</div>
</div>
<div className="content">
{/* 映射关系:path => Component */}
<Routes>
<Route path="/" element={<Navigate to="/home" />}></Route>
<Route path="/home" element={<Home />}>
{/* 嵌套路由 */}
<Route path="/home" element={<HomeRecommend />}></Route>
<Route path="/home/recommend" element={<HomeRecommend />}></Route>
<Route path="/home/ranking" element={<HomeRanking />}></Route>
</Route>
<Route path="/about" element={<About />}></Route>
<Route path="/login" element={<Login />}></Route>
<Route path="/category" element={<Category />}></Route>
<Route path="/order" element={<Order />}></Route>
<Route path="*" element={<NotFound />}></Route>
</Routes>
</div>
<div className="footer">Footer</div>
</div>
);
}
}
export default withRouter(App);