UNPKG

utquidem

Version:

The meta-framework suite designed from scratch for frontend-focused modern web development.

493 lines (348 loc) 9.85 kB
--- title: router sidebar_position: 5 --- :::info 补充信息 基于 [react-router](https://reactrouter.com/web/guides/start) 的路由解决方案。 ::: :::caution 注意 使用该 API 前,请确认没有禁用 [router 插件](#) ::: ## hooks ### useHistory ```ts function useHistory<HistoryLocationState = H.LocationState>(): H.History<HistoryLocationState>; ``` 用于获取 `history` 实例 ```tsx import { useHistory } from "@modern-js/runtime/router"; export function HomeButton() { let history = useHistory(); function handleClick() { history.push("/home"); } return ( <button type="button" onClick={handleClick}> Go home </button> ); } ``` ### useLocation ```ts function useLocation<S = H.LocationState>(): H.Location<S>; ``` `useLocation` 返回当前 url 对应的 [location](https://reactrouter.com/web/api/location) 对象。每当路由更新的时候,都会拿到一个新的 `location` 对象。 ```ts import React from "react"; import { bootstrap, createApp } from '@modern-js/runtime'; import { router } from '@modern-js/runtime/plugins'; import { BrowserRouter as Router, Switch, useLocation } from "@modern-js/runtime/router"; function usePageViews() { let location = useLocation(); React.useEffect(() => { ga.send(["pageview", location.pathname]); }, [location]); } function App() { usePageViews(); return <Switch>...</Switch>; } ``` ### useParams ```ts function useParams< Params extends { [K in keyof Params]?: string } = {} >(): Params; ``` `useParams` 返回一个 key/value 的键值对表示路由中的参数信息它等同于 `<Route >` 组件中的 `match.params` 值 ```tsx import React from "react"; import { Switch, Route, useParams } from "@modern-js/runtime/router"; function BlogPost() { const { slug } = useParams(); return <div>Now showing post {slug}</div>; } function App() { returnn <Switch> <Route exact path="/"> <div>home</div> </Route> <Route path="/blog/:slug"> <BlogPost /> </Route> </Switch> } ``` ### useRouteMatch ```ts function useRouteMatch< Params extends { [K in keyof Params]?: string } = {} >(): match<Params>; function useRouteMatch< Params extends { [K in keyof Params]?: string } = {} >( path: string | string[] | RouteProps, ): match<Params> | null; ``` `useRouteMatch` 和 `<Route />` 一样是对路由进行匹配,但无须去渲染 `<Route />` 组件,便能获取到当前匹配结果 ## 组件 ### Link ```ts interface Link<S = H.LocationState> extends React.ForwardRefExoticComponent< React.PropsWithoutRef<LinkProps<S>> & React.RefAttributes<HTMLAnchorElement> > {} ``` 可以使用 `Link` 组件进行路由跳转 ```ts <Link to="/about">About</Link> ``` #### LinkProps **to** 类型:`string | object | function` `string` ```ts <Link to="/courses?sort=name" /> ``` `object` ```tsx <Link to={{ pathname: "/courses", search: "?sort=name", hash: "#the-hash", state: { fromDashboard: true } }} /> ``` `function` ```tsx <Link to={location => ({ ...location, pathname: "/courses" })} /> <Link to={location => `${location.pathname}?sort=name`} /> ``` **replace** 类型:`boolean` 当设置为 `true` 时,在跳转的时候替换掉 history 栈中的栈顶路由,而不是添加一个新路由 **component** 类型:`Component` 如果你想自定义你自己的路由跳转的组件,可以通过传入 `component` 来实现 ```tsx simply do so by passing it through the component prop.const FancyLink = React.forwardRef((props, ref) => ( <a ref={ref} {...props}>💅 {props.children}</a> )) <Link to="/" component={FancyLink} /> ``` ### NavLink ```ts interface NavLink<S = H.LocationState> extends React.ForwardRefExoticComponent< React.PropsWithoutRef<NavLinkProps<S>> & React.RefAttributes<HTMLAnchorElement> > {} ``` `NavLink` 是一种特殊的 [Link](#link) 组件,当 `NavLink` 对应路由匹配到当前 `url`, 会给 `NavLink` 所渲染的元素添加一些额外的样式 #### NavLinkProps **activeClassName** 类型:`string` 设置路由匹配时额外 class ```tsx <NavLink to="/faq" activeClassName="selected"> FAQs </NavLink> ``` **activeStyle** 类型:`object` 设置路由匹配时额外的样式 ```tsx <NavLink to="/faq" activeStyle={{ fontWeight: "bold", color: "red" }} > FAQs </NavLink> ``` **exact** 类型:`boolean` **strict** 类型:`boolean` **isActive** 类型:`function` 如果你想自定义当前 Link 是否激活的逻辑,可以使用 `isActive` ```tsx <NavLink to="/events/123" isActive={(match, location) => { if (!match) { return false; } // only consider an event active if its event id is an odd number const eventID = parseInt(match.params.eventID); return !isNaN(eventID) && eventID % 2 === 1; }} > Event 123 </NavLink> ``` **location** 类型:`object` `NavLink` 默认会和当前的 `histroy.location` 进行匹配,判断是否处于激活状态如果你想指定要匹配的 `location` 对象,可以使用该参数 **area-current** 类型:`string` 参考 [aria-current](https://www.w3.org/TR/wai-aria-1.1/#aria-current) ### Prompt ```ts interface PromptProps { message: string | ((location: H.Location, action: H.Action) => string | boolean); when?: boolean; } class Prompt extends React.Component<PromptProps, any> {} ``` `Prompt` 组件可用于在页面跳转前,进行二次确认是否跳转 ```tsx <Prompt when={formIsHalfFilledOut} message="Are you sure you want to leave?" /> ``` #### PromptProps **message** 类型:`string` | `function` 在页面跳转前的二次确认提示信息,支持传入函数形式 ```tsx <Prompt message={(location, action) => { if (action === 'POP') { console.log("Backing up...") } return location.pathname.startsWith("/app") ? true : `Are you sure you want to go to ${location.pathname}?` }} /> ``` **when** 类型:`boolean` 当 `when` 为 `true` 时,才会在页面跳转前展示二次确认提示 ### Route ```ts interface RouteProps< Path extends string = string, Params extends { [K: string]: string | undefined } = ExtractRouteParams<Path, string> > { location?: H.Location; component?: React.ComponentType<RouteComponentProps<any>> | React.ComponentType<any>; render?: (props: RouteComponentProps<Params>) => React.ReactNode; children?: ((props: RouteChildrenProps<Params>) => React.ReactNode) | React.ReactNode; path?: Path | Path[]; exact?: boolean; sensitive?: boolean; strict?: boolean; } class Route<T extends {} = {}, Path extends string = string> extends React.Component< RouteProps<Path> & OmitNative<T, keyof RouteProps>, any > {} ``` `Route` 组件用于定义路由 #### component 类型:`React.ComponentType` 当路由匹配成功,会渲染传入 `component` 的组件 ```tsx import React from "react"; import { Route } from "@modern-js/runtime/router"; // All route props (match, location and history) are available to User function User(props) { return <h1>Hello {props.match.params.username}!</h1>; } function App() { return <Route path="/user/:username" component={User} />; } ``` :::tip 提示 如果 component 是一个 inline function,如 `<Route path="/user/:username" component={() => 'hello'} />`,因为每次 rerender 的时候,component 都会是一个新的 `type`,所以 component 组件会先 unmount,再 mount我们需要避免这种写法,或者使用 render 代替 component ::: #### render 类型:`(props: RouteComponentProps<Params>) => React.ReactNode` 允许使用 `inline function` 进行渲染,同时不会有 `component` remounting 的问题 ```tsx import React from "react"; import { Route } from "@modern-js/runtime/router"; function App() { <Route path="/home" render={() => <div>Home</div>} /> } ``` :::info 注 component 的优先级高于 render ::: #### children 类型:`((props: RouteChildrenProps<Params>) => React.ReactNode) | React.ReactNode` 如果在路由匹配或不匹配的情况下,都需要渲染一些内容,那么可以使用 `children` 参数 ```tsx function ListItemLink({ to, ...rest }) { return ( <Route path={to} children={({ match }) => ( <li className={match ? "active" : ""}> <Link to={to} {...rest} /> </li> )} /> ); } function App() { return <ul> <ListItemLink to="/somewhere" /> <ListItemLink to="/somewhere-else" /> </ul>; } ``` #### path 类型:`string | string[]` 符合 [path-to-regexp@^1.7.0](https://github.com/pillarjs/path-to-regexp/tree/v1.7.0) 匹配规则的 url 字符串或数组。 ```tsx <Route path="/users/:id"> <User /> </Route> <Route path={["/users/:id", "/profile/:id"]}> <User /> </Route> ``` #### exact 类型:`boolean` 默认值:`false` 当 `exact` 值为 `true` 时,会进行准确匹配 | path | location.pathname | exact | matches? | | - | - | - | - | | /one | /one/two | true | no | | /one | /one/two | false | yes | #### strict 类型:`boolean` 默认值:`false` 当 `strict` 值为 `true` 时,会进行严格匹配若 `path` 以 '/' 结尾,那么 `location.pathname` 也需要以 '/' 结尾,才能匹配 | path | location.pathname | matches? | | - | - | - | | /one/ | /one | no | | /one/ | /one/ | yes | | /one/| /one/two | yes | #### sensitive 类型:`boolean` 默认值:`false` 当 `sensitive` 设置为 `true`,则 path 大小写不敏感 #### location 类型:`object` ## 更多底层 API 若想要了解更多的底层 API 信息,可至 [react-router 官网](https://reactrouter.com/web/guides/start) 查看。