网站建设市场调研,浦东区网站建设,网站提速怎么做,教育考试类网站建设文章目录 基本格式createBrowserRouterType Declarationroutesbasenamefuture and window ... 省略 RouterProviderfall上述文本提到 createBrowserRouter 函数的一个特性#xff1a;在非服务器端渲染应用程序时#xff0c;当它挂载时会初始化所有匹配的路由加载器。… 文章目录 基本格式createBrowserRouterType Declarationroutesbasenamefuture and window ... 省略 RouterProviderfall上述文本提到 createBrowserRouter 函数的一个特性在非服务器端渲染应用程序时当它挂载时会初始化所有匹配的路由加载器。在此期间你可以提供 fallbackElement以向用户显示应用程序正在加载的指示。future ... ComponentsAwait 以下内容来自官方文档 https://reactrouter.com/en/main 基本格式
import * as React from react;
import { createRoot } from react-dom/client;
import {createBrowserRouter,RouterProvider,Route,Link,
} from react-router-dom;const router createBrowserRouter([{path: /,element: (divh1Hello World/h1Link toaboutAbout Us/Link/div),},{path: about,element: divAbout/div,},
]);createRoot(document.getElementById(root)).render(RouterProvider router{router} /
);createBrowserRouter
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} /
);Type Declaration
function createBrowserRouter(routes: RouteObject[],opts?: {basename?: string;future?: FutureConfig;hydrationData?: HydrationState;window?: Window;}
): RemixRouter;routes
An array of Route objects with nested routes on the children property.
createBrowserRouter([{path: /,element: Root /,loader: rootLoader,children: [{path: events/:id,element: Event /,loader: eventLoader,},],},
]);Route定义为:
const router createBrowserRouter([{// it renders this elementelement: Team /,// when the URL matches this segmentpath: teams/:teamId,// with this data loaded before renderingloader: async ({ request, params }) {return fetch(/fake/api/teams/${params.teamId}.json,{ signal: request.signal });},// performing this mutation when data is submitted to itaction: async ({ request }) {return updateFakeTeam(await request.formData());},// and renders this element in case something went wrongerrorElement: ErrorBoundary /,},
]);RouteObject对象的声明为:
interface RouteObject {path?: string;index?: boolean;children?: React.ReactNode;caseSensitive?: boolean;id?: string;loader?: LoaderFunction;action?: ActionFunction;element?: React.ReactNode | null;Component?: React.ComponentType | null;errorElement?: React.ReactNode | null;ErrorBoundary?: React.ComponentType | null;handle?: RouteObject[handle];shouldRevalidate?: ShouldRevalidateFunction;lazy?: LazyRouteFunctionRouteObject;
}对于Path:动态路由参数, 可以在loader, action中通过params直接点出 或者使用useParams()钩子来获取该参数
Route// this path will match URLs like// - /teams/hotspur// - /teams/realpath/teams/:teamId// the matching param will be available to the loaderloader{({ params }) {console.log(params.teamId); // hotspur}}// and the actionaction{({ params }) {}}element{Team /}
/;// and the element through useParams
function Team() {let params useParams();console.log(params.teamId); // hotspur
}你可以定义多个动态参数 都可以通过 . 运算符获取到
Route path/c/:categoryId/p/:productId /;
// both will be available
params.categoryId;
params.productId;可选参数 通过在后面加上 ?
Route// this path will match URLs like// - /categories// - /en/categories// - /fr/categoriespath/:lang?/categories// the matching param might be available to the loaderloader{({ params }) {console.log(params[lang]); // en}}// and the actionaction{({ params }) {}}element{Categories /}
/;// and the element through useParams
function Categories() {let params useParams();console.log(params.lang);
}当然可以同时用动态参数和可选参数
模糊匹配所有的 * 参数
Route// this path will match URLs like// - /files// - /files/one// - /files/one/two// - /files/one/two/threepath/files/*// the matching param will be available to the loaderloader{({ params }) {console.log(params[*]); // one/two}}// and the actionaction{({ params }) {}}element{Team /}
/;// and the element through useParams
function Team() {let params useParams();console.log(params[*]); // one/two
}布局路由
Routeelement{divh1Layout/h1Outlet //div}
Route path/ element{h2Home/h2} /Route path/about element{h2About/h2} /
/Route组件留出子路由要渲染的位置,仅此而已index索引路由 url为父路径时显示的组件
Route path/teams element{Teams /}Route index element{TeamsIndex /} /Route path:teamId element{Team /} /
/Route外层的Route有一个路径path为/teams并渲染了一个组件Teams /。在这个路由内部有另一个带有index属性的嵌套的Route。这意味着当路径匹配/teams时组件TeamsIndex /将被呈现到其父级路由的Outlet中在这种情况下是Teams /。此外还有另一个带有path:teamId的嵌套路由表示当路径匹配/teams/:teamId时将呈现组件Team /。
children: 嵌套路由caseSensitive: 表示对路径中大小写敏感Instructs the route to match case or not:
Route caseSensitive path/wEll-aCtuA11y /Will match “wEll-aCtuA11y”Will not match “well-actua11y”
loader每一个路由都能定义一个loader函数来为路由组件渲染之前提供数据
createBrowserRouter([{element: Teams /,path: teams,loader: async () {return fakeDb.from(teams).select(*);},children: [{element: Team /,path: :teamId,loader: async ({ params }) {return fetch(/api/teams/${params.teamId}.json);},},],},
]);通过 调用loader函数获得的数据可以通过 useLoaderData钩子拿到useLoaderData: This hook provides the value returned from your route loader.
import {createBrowserRouter,RouterProvider,useLoaderData,
} from react-router-dom;function loader() {return fetchFakeAlbums();
}export function Albums() {const albums useLoaderData();// ...
}const router createBrowserRouter([{path: /,loader: loader,element: Albums /,},
]);ReactDOM.createRoot(el).render(RouterProvider router{router} /
);在调用路由操作之后数据将自动重新验证并从加载器返回最新的结果。请注意useLoaderData 不会启动抓取。它只是读取 React Router 在内部管理的抓取结果因此您不必担心在重新呈现的原因之外的情况下重新获取数据。这也意味着在重新呈现之间返回的数据是稳定的因此您可以安全地将其传递给 React hooks如 useEffect中的依赖数组。它只在再次调用加载器后在执行操作或特定导航后才会更改。在这些情况下标识将更改即使值没有更改。您可以在任何组件或任何自定义 hook 中使用此钩子而不仅仅是在 Route 元素中。它将返回上下文中最近路由的数据。params: 由url中解析的动态参数会放在params中并传递给loader函数
createBrowserRouter([{path: /teams/:teamId,loader: ({ params }) {return fakeGetTeam(params.teamId);},},
]);request:
ahref{props.to}onClick{(event) {event.preventDefault();navigate(props.to);}}
/React router阻止浏览器将请求request发送给server, 而是转给了loader函数
function loader({ request }) {const url new URL(request.url);const searchTerm url.searchParams.get(q);return searchProducts(searchTerm);
}返回 response可以返回fetch()发送异步请求(ajax, axios)的结果,也可以自定义返回结果
// an HTTP/REST API
function loader({ request }) {return fetch(/api/teams.json, {signal: request.signal,});
}// or even a graphql endpoint
function loader({ request, params }) {return fetch(/_gql, {signal: request.signal,method: post,body: JSON.stringify({query: gql...,params: params,}),});
}function loader({ request, params }) {const data { some: thing };return new Response(JSON.stringify(data), {status: 200,headers: {Content-Type: application/json; utf-8,},});
}react router会自动调用 response.json()
function SomeRoute() {const data useLoaderData();// { some: thing }
}在loader中抛出异常
function loader({ request, params }) {const res await fetch(/api/properties/${params.id});if (res.status 404) {throw new Response(Not Found, { status: 404 });}return res.json();
}会渲染路由中定义的 errorElement组件action: 进行写操作的函数
Routepath/song/:songId/editelement{EditSong /}action{async ({ params, request }) {let formData await request.formData();return fakeUpdateSong(params.songId, formData);}}loader{({ params }) {return fakeGetSong(params.songId);}}
/在应用发起一个非get请求时被调用 比如按钮点击
// forms
Form methodpost action/songs /;
fetcher.Form methodput action/songs/123/edit /;// imperative submissions
let submit useSubmit();
submit(data, {method: delete,action: /songs/123,
});
fetcher.submit(data, {method: patch,action: /songs/123/edit,
});element / Component: 要渲染的组件 errorElement / ErrorBoundary: 异常时渲染的组件当在loader, action函数执行或者组件渲染时抛出异常, 就不会渲染element组件, 而是用error path的组件 errorElement渲染, 该异常可以用 useRouteError获取lazy :
let routes createRoutesFromElements(Route path/ element{Layout /}Route patha lazy{() import(./a)} /Route pathb lazy{() import(./b)} //Route
);basename
The basename of the app for situations where you can’t deploy to the root of the domain, but a sub directory.
createBrowserRouter(routes, {basename: /app,
});future and window … 省略 All data router objects are passed to this component to render your app and enable the rest of the data APIs
import {createBrowserRouter,RouterProvider,
} from react-router-dom;const router createBrowserRouter([{path: /,element: Root /,children: [{path: dashboard,element: Dashboard /,},{path: about,element: About /,},],},
]);ReactDOM.createRoot(document.getElementById(root)).render(RouterProviderrouter{router}fallbackElement{BigSpinner /}/
);fall上述文本提到 createBrowserRouter 函数的一个特性在非服务器端渲染应用程序时当它挂载时会初始化所有匹配的路由加载器。在此期间你可以提供 fallbackElement以向用户显示应用程序正在加载的指示。
这个特性的目的是在加载路由数据时提供一个加载过程中的占位元素fallback element使用户在等待加载完成时能够看到一些界面反馈而不是一片空白。举例来说你可以在 createBrowserRouter 中添加 fallbackElement 选项像这样
createBrowserRouter(routes, {fallbackElement: divLoading.../div,
});这样当路由加载的过程中页面将显示 “Loading…”以告诉用户应用程序正在处理数据避免用户在加载过程中感到不确定或无反馈。
future … Components import { Await, useLoaderData } from react-router-dom;function Book() {const { book, reviews } useLoaderData();return (divh1{book.title}/h1p{book.description}/pReact.Suspense fallback{ReviewsSkeleton /}Awaitresolve{reviews}errorElement{divCould not load reviews /div}children{(resolvedReviews) (Reviews items{resolvedReviews} /)}//React.Suspense/div);
}这段代码是一个使用 React Router 的 useLoaderData 和 Await 组件的 React 组件。让我解释一下它的主要部分
useLoaderData 是 React Router 提供的一个 hook用于获取路由加载器loader返回的数据。在这里通过 useLoaderData 获取了 book 和 reviews。在 return 中首先渲染了 book 的标题和描述。使用了 React 的 Suspense 组件它接受 fallback 属性指定在子组件加载过程中显示的占位元素。在这里如果 reviews 尚未加载完成将显示一个 ReviewsSkeleton 组件用作加载占位符。使用 Await 组件包装了 reviews 的加载。Await 组件接受 resolve 属性指定需要等待的 Promise。如果 resolve Promise 处于 pending 状态它会渲染 fallback 中的占位元素如果 Promise 处于 resolved 状态它会调用 children 函数并将 resolved 的数据传递给它。在 children 函数中渲染了一个 Reviews 组件传递了从 reviews 获取的 resolved 数据。
总体来说这段代码的目的是展示书籍的标题和描述同时以异步方式加载书籍的评论。在加载评论的过程中会显示一个加载中的占位符确保用户在等待数据加载完成时能够看到一些界面反馈。如果加载评论失败将显示一个错误提示。