1. 注册路由
路由的注册和vue框架中类似,注册过后需要在地址栏输入你想要进去的页面。
// 引入
import { createRoot } from "react-dom/client";
import { createBrowserRouter,RouterProvider,Route,Link }from "react-router-dom";
// 引入组件
import Home from "./views/home/Home.jsx";
import User from "./views/user/User.jsx";
import Root from "./views/root/Root.jsx";
// 注册路由
const router = createBrowserRouter([
{
path: "/",
element: <Home />,
},
{
path: "user",
element: <User />,
},
{
path: "root",
element: <Root />,
},
]);
createRoot(document.getElementById("root")).render(<RouterProvider router={router} />);
在实际中肯定不是通过在地址栏输入不同路由来切换页面的,接下来就通过标签和js语法写代码来实现页面(组件)的切换。
2. 切换路由——换组件
2.1. 利用标签跳<Link to="/路由名"></Link>
2.2. js跳转——useNavigate
// 引入
import { useNavigate } from "react-router-dom";
let router = useNavigate();
let fn = () => {
// router('root');
router({ pathname: "root" });
}
3. 页面跳转传参
3.1. state传参——{state:传的参数}
传参:state中可以穿字符串、对象等等。
获取:目标页面通过官方提供的useLocation方法来接收传过来的参数,通过useLocation().state取到数据
// 传参
router({ pathname: "/root" },{state:{goodsname:"隔离",price:159}});
// 目标页面接收
import { useLocation } from "react-router-dom";
let obj = useLocation();
useEffect(() => {
console.log(obj.state);
}, []);
传的参数在网址中看不见。
3.2. url传参——?参数或search:'字符串参数'
传参:Link标签跳转:<Link to="/user?userid=12&username=rosy">user</Link>
js语法传参: router({ pathname: "/user", search:'userid=12&username=rosy' })
获取:useLocation().search
需要注意的是,这种传参方式,目标页面接收到的参数是query字符串,我们需要将这个字符串处理成对象的行,才能通过对象点语法取到数据。
import React from "react";
import { useLocation } from "react-router-dom";
export default function User() {
let routes = useLocation();
// 解析当前网站的querystring 例:'email=123&count=11'
let querystring = (str) => {
let obj = {};
// ? 前面有就执行后面代码 没有就不执行
// let arr = str.split('?')[1]?.split('&').map(el => el.split('='));
// 易理解方法
let query = str.split("?")[1];
// 没传参
if (!query) {
return obj;
}
// 传参了,切割字符串
let arr = query.split("&").map((el) => el.split("="));
arr.forEach((el) => {
// el=[['email','123],['page','22']]
obj[el[0]] = el[1];
});
return obj;
};
let queryobj = querystring(routes.search);
console.log(queryobj);
return (
<div>
<h3>User</h3>
</div>
);
}
参数可以在网址中看到。
3.3. 动态路由传参
// 注册路由时
{
// 动态传参
// path: "/login/:date",
// 传多个
path: "/login/:date/:time",
element: <Login />,
},
// 主页跳转到login页面
// router({ pathname: "/login/1234" });
// 传多个
router({ pathname: "/login/1234/hi" });
// login页面接收
let data = useParams();
console.log(data);
参数可以在网址中看到。传过来的参数就是对象的形式,但不推荐使用,因为写代码时注册路由和跳转传参都要写,麻烦。
4. 嵌套路由(子路由)
注册路由:父路由的children属性,是个数组。
注:二级路由不能写成'/a1',这样写真正的网址是'http://ip:port/a1';
而'a1'指的网址是当前网页的网址的最后添加/a1,也就是'http://ip:port/user/a1
占位组件:<Outlet></Outlet>
// 注册子路由
{
path: "/user",
element: <User />,
children: [
{
path: "/user/info",
element: <Info />,
},
{
path: "collection",
element: <Collection />,
},
],
}
// 父组件return的模板
<div>
<h3>User</h3>
<Link to='/user/info'>info</Link><br />
<Link to='collection'>collection</Link>
{/* 占位组件 */}
<Outlet></Outlet>
</div>
5. 路由健全
5.1 路由守卫——loader
相当于vue中的路由守卫,有些页面需要一定条件才能访问,比如说个人中心页面需要登录过后才能访问。
// 独享守卫 写在单个路由中,作为属性
loader: () => {
// 假设做是否登录判断
if (false) {
return null;
} else {
return redirect('/login')
}
}
// 全局守卫 写在路由前面 作为函数
let loader = () => {
// 假设做是否登录判断
if (false) {
return null;
} else {
return redirect("/login");
}
};
5.2 重定向——redirect
相当于自动帮你切网址