react PC端项目构建TS,react@18.2.0+antd+vite+axios+redux+sass+ts 完整版代码下载:
https://download.csdn.net/download/randy521520/88922625
react PC端项目构建,react@18.2.0+antd+vite+axios+redux+sass完整版代码下载:
https://download.csdn.net/download/randy521520/88922569
react移动端项目构建TS,react@18.2.0+react-vant+vite+axios+redux+sass+ts完整版代码下载:
https://download.csdn.net/download/randy521520/88917557
react移动端项目构建,react@18.2.0+react-vant+vite+axios+redux+sass完整版代码下载:
https://download.csdn.net/download/randy521520/88917543
一、react-router简介
react-router 是一个用于处理 React 应用程序中路由管理的库,它提供了一种简单而强大的方式来实现单页面应用程序(SPA)中的路由控制。通过 react-router,可以轻松地定义应用程序的不同路由,使用户能够在应用程序中浏览不同的页面或视图。数据路由器比普通的路由器支持加载器、操作、提取器等功能。
二、数据路由器
1.createBrowserRouter:创建BrowserRouter数据路由器
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
createBrowserRouter,
RouterProvider,
} from "react-router-dom";
import Root, { rootLoader } from "./routes/root";
import Team, { teamLoader } from "./routes/team";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
loader: rootLoader,
children: [
{
path: "team",
element: <Team />,
loader: teamLoader,
},
],
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<RouterProvider router={router} />
);
2.createHashRouter:创建createHashRouter数据路由器
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
createHashRouter,
RouterProvider,
} from "react-router-dom";
import Root, { rootLoader } from "./routes/root";
import Team, { teamLoader } from "./routes/team";
const router = createHashRouter([
{
path: "/",
element: <Root />,
loader: rootLoader,
children: [
{
path: "team",
element: <Team />,
loader: teamLoader,
},
],
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<RouterProvider router={router} />
);
3.createMemoryRouter:创建ceateMemoryRouter数据路由器
import {
RouterProvider,
createMemoryRouter,
} from "react-router-dom";
import * as React from "react";
import {
render,
waitFor,
screen,
} from "@testing-library/react";
import "@testing-library/jest-dom";
import CalendarEvent from "./routes/event";
test("event route", async () => {
const FAKE_EVENT = { name: "test event" };
const routes = [
{
path: "/events/:id",
element: <CalendarEvent />,
loader: () => FAKE_EVENT,
},
];
const router = createMemoryRouter(routes, {
initialEntries: ["/", "/events/123"],
initialIndex: 1,
});
render(<RouterProvider router={router} />);
await waitFor(() => screen.getByRole("heading"));
expect(screen.getByRole("heading")).toHaveTextContent(
FAKE_EVENT.name
);
});
4.createStaticHandler:创建createStaticHandler数据路由器
import {
createStaticHandler,
createStaticRouter,
StaticRouterProvider,
} from "react-router-dom/server";
import Root, {
loader as rootLoader,
ErrorBoundary as RootBoundary,
} from "./root";
const routes = [
{
path: "/",
loader: rootLoader,
Component: Root,
ErrorBoundary: RootBoundary,
},
];
export async function renderHtml(req) {
let { query, dataRoutes } = createStaticHandler(routes);
let fetchRequest = createFetchRequest(req);
let context = await query(fetchRequest);
if (context instanceof Response) {
throw context;
}
let router = createStaticRouter(dataRoutes, context);
return ReactDOMServer.renderToString(
<React.StrictMode>
<StaticRouterProvider
router={router}
context={context}
/>
</React.StrictMode>
);
}
5.createStaticRouter:创建createStaticRouter数据路由器
import {
createStaticHandler,
createStaticRouter,
StaticRouterProvider,
} from "react-router-dom/server";
import Root, {
loader as rootLoader,
ErrorBoundary as RootBoundary,
} from "./root";
const routes = [
{
path: "/",
loader: rootLoader,
Component: Root,
ErrorBoundary: RootBoundary,
},
];
export async function renderHtml(req) {
let { query, dataRoutes } = createStaticHandler(routes);
let fetchRequest = createFetchRequest(req);
let context = await query(fetchRequest);
if (context instanceof Response) {
throw context;
}
let router = createStaticRouter(dataRoutes, context);
return ReactDOMServer.renderToString(
<React.StrictMode>
<StaticRouterProvider
router={router}
context={context}
/>
</React.StrictMode>
);
}
6.RouterProvider:数据路由器组件
- router:创建的路由器
- fallbackElement:路由加载时显示的备用元素,如果路由加载过程中出现延迟或错误,可以显示此备用元素
- future:预加载和延迟加载的配置信息。
7.StaticRouterProvider:静态数据路由器组件,使用createStaticRouter创建的路由器 - context: 静态路由上下文对象,用于在服务器端渲染时传递路由信息。
- router:创建的路由器
- hydrate: 用于将服务器端生成的内容与客户端的事件处理逻辑连接起来。
- nonce: 用于安全策略的一次性随机数
8.创建数据路由器相关参数 - id:路由的唯一标识符,id: ‘id’
- path:路由的路径,path: ‘/’
- element:React 元素,用于渲染路由内容,element: <></>
- children:子路由,children: [{}]
- index:指示这是一个索引路由,索引路由是指当用户访问应用程序的根路径时所匹配的路由,常用于子路由,index: false
- caseSensitive:指示路由是否区分大小写,react-router V6版本无效果,caseSensitive: false
- lazy:用于定义懒加载路由的函数, lazy:()=>import(componentPath)
- loader:用于懒加载路由的加载器,loader: async ({params,request,context}) => {}
- action:路由提交事件,action: async ({params,request,context}) => {}
- errorElement: <></>:错误时显示的元素。
- Component: ‘’:React 组件类型。
- hasErrorBoundary: false:指示路由是否有错误边界。
- shouldRevalidate: false:指示是否应该重新验证路由。
- ErrorBoundary: <></>:错误边界组件。
- handle: ‘’:路由的处理函数。
- hydrateFallbackElement: <></>:用于服务端渲染时的回退元素。
- HydrateFallback: <></>:用于服务端渲染时的回退组件。
三、数据路由器之useMatches:返回页面上的当前路由匹配项
import {useMatches} from "react-router-dom";
const List = () => {
console.log(useMatches())
return (<>列表页</>);
};
export default List;
四、数据路由器之useNavigation:获取导航的所有信息
import {useNavigation} from "react-router-dom";
const List = () => {
console.log(useNavigation())
return (<>列表页</>);
};
export default List;
五、数据路由器之useLoaderData:处理加载数据,路由器需配置loader
1.路由器配置
import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";
const routes = createBrowserRouter([{
path: '/',
element: <Navigate to="/home" replace/>,
}, {
path: '/home',
element: <Home/>,
}, {
path: '/list/:id',
element: <List/>,
loader: async ({params,request,context}) => {
console.log(params,request,context)
return {useId:'ACTION'}
}
}]);
export default routes;
2.跳转有加载器的路由页面
import {useNavigate} from "react-router-dom";
const Home = () => {
const navigate = useNavigate();
const goRouter = () => {
navigate('/list/1')
}
return (<>
<button onClick={goRouter}>跳转list</button>
</>);
};
export default Home;
3.加载器路由页面
import {useLoaderData} from "react-router-dom";
const List = () => {
console.log(useLoaderData())
return (<>列表页</>);
};
export default List;
六、数据路由器之useSubmit、<Form>组件:处理提交的Hook,useSubmit(formData,option)
1.option配置
- method: 用于提交方法。默认为 “GET”。
- action: 用于提交路径。默认为当前路由的路径,会跳转到该路由
- encType: 用于提交编码类型。默认为 “application/x-www-form-urlencoded”。
- fetcherKey: 当 navigate=false 时使用的特定 fetcherKey。
- navigate: 当设置为 false 时,将使用 fetcher 而不是导航。
- replace: 设置为 true 时,将替换浏览器历史堆栈中的当前条目。默认为 false。
- state: 添加到此导航的历史堆栈条目的状态对象。
- relative: 确定表单操作相对于路由层次结构还是路径名。如果要选择退出路由层次结构而是基于 / 分隔的 URL 段路由,则使用此选项。
- preventScrollReset: 在基于浏览器的环境中,使用 组件时,防止在此导航后重置滚动。
- unstable_flushSync: 为此导航的状态更新启用 flushSync。
- unstable_viewTransition: 在此提交导航上启用视图过渡。
1.路由器配置
import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";
const routes = createBrowserRouter([{
path: '/',
element: <Navigate to="/home" replace/>,
}, {
path: '/home',
element: <Home/>,
}, {
path: '/list/:id',
element: <List/>,
action: async ({params,request,context}) => {
console.log(params,request,context)
let formData = await request.formData();
return {useId:params.id,name:formData.get('name')}
},
}]);
export default routes;
2.跳转有action的路由页面
import {useSubmit} from "react-router-dom";
const Home = () => {
const submit = useSubmit();
const goRouter = () => {
submit({name:'张三'}, { method: "post", action: "/list/1" });
}
return (<>
<button onClick={goRouter}>跳转list</button>
</>);
};
export default Home;
3.获取actipn数据:useActionData
import {useActionData} from "react-router-dom";
const List = () => {
const data = useActionData();
console.log(data)
return (<>列表页</>);
};
export default List;
4.除了使用useSubmit跳转,还可以使用组件
- method:表单数据提交的方式,可以是 “get”、“post”、“put”、“patch” 或 “delete”.
- encType:表单数据的编码类型,可以是 “application/x-www-form-urlencoded”、“multipart/form-data” 或 “text/plain”.
- action:表单提交的目标 URL.
- onSubmit:处理表单提交事件的回调函数.
- fetcherKey:指定表单提交时使用的fetcher key.
- navigate:指定是否在提交表单后进行页面导航.
- preventScrollReset:指定是否阻止表单提交后的滚动位置重置.
- relative:导航相对位置的方式,可以是 “route” 或 “path”.
- reloadDocument:指定是否在提交表单后重新加载文档.
- replace:指定是否使用替换导航.
- state:要传递的状态数据.
- unstable_viewTransition:指定是否使用不稳定的视图过渡.
import {Form} from "react-router-dom";
const Home = () => {
return (<>
<Form method="post" action="/list/1">
<button type="submit">跳转list</button>
</Form>
</>);
};
export default Home;
七、数据路由器之useRouteLoaderData:子路由获取父路由的加载数据
1.路由器配置
import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";
const routes = createBrowserRouter([{
path: '/',
element: <Navigate to="/home" replace/>,
}, {
id:'home',
path: '/home',
element: <Home/>,
loader: ()=>{
return {name:'home'}
},
children:[{
path: 'list',
element: <List/>,
}]
}]);
export default routes;
2.父路由页面
import {Outlet} from "react-router-dom";
const Home = () => {
return (<>
<div>home页</div>
<Outlet/>
</>);
};
export default Home;
3.子路由页面
import { useRouteLoaderData} from "react-router-dom";
const List = () => {
const parentLoaderData = useRouteLoaderData('home');
console.log(parentLoaderData)
return (<>列表页</>);
};
export default List;
八、数据路由器之useBlocker:用于处理阻塞操作的 Hook,页面离开前处理一些操作,如:是否确认离开该页面
import {useBlocker, useNavigate} from "react-router-dom";
const Home = () => {
const navigate = useNavigate();
let blocker = useBlocker(({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname);
const goRouter = () => {
navigate('/list/1')
}
return (<>
<button onClick={goRouter}>跳转列表</button>
{blocker.state === "blocked" ? (
<div>
<p>是否离开hone页</p>
<button onClick={() => blocker.proceed()}>确定</button>
<button onClick={() => blocker.reset()}>取消</button>
</div>
) : null}
</>);
};
export default Home;
九、数据路由器之useFormAction:自动解析 submit 的操作
import {useFormAction,useSubmit} from "react-router-dom";
const Home = () => {
let submit = useSubmit();
let action = useFormAction();
const goRouter = () => {
submit({}, { action });
}
return (<>
<button onClick={goRouter}>跳转列表</button>
</>);
};
export default Home;
十、数据路由器之unstable_usePrompt:离开页面之前给出弹框提示
import {unstable_usePrompt, useNavigate} from "react-router-dom";
const Home = () => {
let navigate = useNavigate()
const goRouter = () => {
navigate('/list/1')
}
unstable_usePrompt({
message: "是否离开页面?",
when: ({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname,
});
return (<>
<button onClick={goRouter}>跳转列表</button>
</>);
};
export default Home;
十一、数据路由器之useFetcher:不更改 URL 的情况下调用其他导航的loader、action
1.fetcher.submit(formData,option):提交数据,路由需配置action
2.fetcher.load(href):加载对应href加载器,路由需配置loader
3.fetcher.state:提取器状态
- idle:空闲状态
- submitting:使用 POST、PUT、PATCH 或 DELETE 进行提取程序提交,正在调用路由操作
- loading:提取器正在调用加载程序
4.fetcher.data:从加载程序或操作返回的数据存储在此处。一旦设置了数据,即使通过重新加载和重新提交,它也会保留在提取器上。
5.fetcher.formData:使用 <fetcher.Form> 或 fetcher.submit() 时的表单数据I。
6.fetcher.json:使用 fetcher.submit(data, { formEncType: “application/json” }) 时,提交的 JSON 可通过 fetcher.json 获得。
7.fetcher.text:使用 fetcher.submit(data, { formEncType: “text/plain” }) 时,提交的文本可通过 fetcher.text 获得。
8.fetcher.formAction:获取提交的url
9.fetcher.formMethod:获取提交的方法
10.使用案例 - 路由器配置
import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";
const routes = createBrowserRouter([{
path: '/',
element: <Navigate to="/home" replace/>,
}, {
path: '/home',
element: <Home/>,
}, {
path: '/list/:id',
element: <List/>,
loader: async ({params,request,context}) => {
return {useId:params.id,name:'loader'}
},
action: async ({params,request,context}) => {
console.log(params,request,context)
let formData = await request.formData();
return {useId:params.id,name:formData.get('name')}
},
}]);
export default routes;
- 跨页面调用list路由的action、loader,页面提交或加载之后会保存在提取器中,可以根据key在其他页面获取
import {useFetcher, useNavigate} from "react-router-dom";
import {useEffect} from "react";
const Home = () => {
const fetcher = useFetcher({key:'home'});
const navigate = useNavigate();
useEffect(() => {
if (fetcher.state === "idle" && !fetcher.data) {
fetcher.load("/list/1");
}
}, [fetcher]);
const goRouter = ()=>{
navigate('/list/1');
}
const onSubmit = ()=>{
fetcher.submit({name:'useFetcher'}, {method:'post',action:'/list/1'});
}
return (<>
<button onClick={onSubmit}>提交数据</button>
<button onClick={goRouter}>跳转list</button>
<div>{JSON.stringify(fetcher.data)}</div>
</>
);
};
export default Home;
- 在list页面获取提取器中的内容
import {useFetcher} from "react-router-dom";
const List = () => {
const fetcher = useFetcher({key:'home'});
return (<>{JSON.stringify(fetcher.data)}</>);
};
export default List;
十二、数据路由器之useFetchers:用于没配置action、loader的路由,获取已配置路由的fetcher
1.路由器配置
import {createBrowserRouter, Navigate} from "react-router-dom";
import Home from "@pages/home/home.jsx";
import List from "@pages/list/list.jsx";
import Detail from "@pages/detail/detail.jsx";
const routes = createBrowserRouter([{
path: '/',
element: <Navigate to="/home" replace/>,
}, {
path: '/home',
element: <Home/>,
}, {
path: '/list/:id',
element: <List/>,
loader: async ({params,request,context}) => {
return {useId:params.id,name:'loader'}
},
action: async ({params,request,context}) => {
console.log(params,request,context)
let formData = await request.formData();
return {useId:params.id,name:formData.get('name')}
},
},{
path:'detail',
element: <Detail/>
}]);
export default routes;
2.跨页面调用list路由的action、loader
import {useFetcher, useNavigate} from "react-router-dom";
import {useEffect} from "react";
const Home = () => {
const fetcher = useFetcher({key:'home'});
const navigate = useNavigate();
useEffect(() => {
if (fetcher.state === "idle" && !fetcher.data) {
fetcher.load("/list/1");
}
}, [fetcher]);
const goRouter = ()=>{
navigate('/detail');
}
const onSubmit = ()=>{
fetcher.submit({name:'useFetcher'}, {method:'post',action:'/list/1'});
}
return (<>
<button onClick={onSubmit}>提交数据</button>
<button onClick={goRouter}>跳转detail</button>
<div>{JSON.stringify(fetcher.data)}</div>
</>
);
};
export default Home;
3.在detail页面获取提取器中的内容,页面刷新之后是获取不到的
import {useFetchers} from "react-router-dom";
import {useEffect, useState} from "react";
const Detail = () => {
const fetchers = useFetchers({key: 'home'});
let [homeFetch,setHomeFetch] = useState({});
useEffect(() => {
setHomeFetch(fetchers[0]);
}, []);
return (<>
{JSON.stringify(homeFetch?.data)}
</>);
};
export default Detail;
十三、其他
1.useRevalidator:用于重新验证的 Hook。
2.useRouteError:处理路由错误的 Hook
3.<ScrollRestoration/>:加载程序完成后,此组件将模拟浏览器在位置更改时的滚动恢复,以确保滚动位置恢复到正确的位置