motainzhang

motainzhang

react-router - 常用知识

58
2019-02-20
react-router - 常用知识

组件-Router

// 用于导航的历史对象
<Router history={history}></Router>

// 一个使用了 HTML5 history API 的高阶路由组件,保证你的 UI 界面和 URL 保持同步
<BrowserRouter
    basename="/calendar" // 添加一个基准URL
    forceRefresh={false} // 当浏览器不支持 HTML5 的 history API 时强制刷新页面
    getUserConfirmation={getConfirmation()} // 导航到此页面前执行的函数
    keyLength={12} // 设置它里面路由的 location.key 的长度。默认是6
></BrowserRouter>

<HashRouter></HashRouter>
// Hash history 不支持 location.key 和 location.state。
// 另外由于该技术只是用来支持旧版浏览器,因此更推荐大家使用 BrowserRouter

forceRefresh: bool

如果为 true,路由器将在页面导航时使用完整页面刷新。您可能只想在不支持 HTML5 历史记录 API 的浏览器中使用它。

const supportsHistory = 'pushState' in window.history
<BrowserRouter forceRefresh={!supportsHistory}/>

getUserConfirmation: func

用于确认导航的函数,默认使用 window.confirm。例如,当从 /a 导航至 /b 时,会使用默认的 confirm 函数弹出一个提示,用户点击确定后才进行导航,否则不做任何处理。译注:需要配合 <Prompt> 一起使用。

// this is the default behavior
const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message)
  callback(allowTransition)
}

<BrowserRouter getUserConfirmation={getConfirmation}/>

keyLength: number

The length of location.key. Defaults to 6.

组件-Switch

如果你访问 /about,那么组件 About User Nomatch 都将被渲染出来,因为他们对应的路由与访问的地址 /about 匹配

// render all
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>

<Switch>只渲染出第一个与当前访问地址匹配的 <Route><Redirect>

// Renders the first child <Route> or <Redirect> that matches the location.
<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/about" component={About} />
  <Route path="/:user" component={User} />
  <Route component={NoMatch} />
</Switch>

组件-Route

<Route
 path="/" // url路径
 exact  // bool 严格匹配 ’/link’与’/’是不匹配的,但是在false的情况下它们是匹配的
 component={IndexPage} // 渲染的组件
/>

<Route
 path="/" // url路径
 exact  // bool 严格匹配 ’/link’与’/’是不匹配的,但是在false的情况下它们是匹配的
 render={() => <div>Home</div>} // 内联渲染
/>

渲染一些内容有以下三种方式:component / render / children

Route 渲染方式

component

指定只有当位置匹配时才会渲染的 React 组件,该组件会接收 route props 作为属性。

const User = ({ match }) => {
  return <h1>Hello {match.params.username}!</h1>
}

<Route path="/user/:username" component={User} />

当你使用 component(而不是 renderchildren)时,Router 将根据指定的组件,使用 React.createElement 创建一个新的 React 元素。这意味着,如果你向 component 提供一个内联函数,那么每次渲染都会创建一个新组件。这将导致现有组件的卸载和新组件的安装,而不是仅仅更新现有组件。当使用内联函数进行内联渲染时,请使用 renderchildren(见下文)。

render: func

使用 render 可以方便地进行内联渲染和包装,而无需进行上文解释的不必要的组件重装。

你可以传入一个函数,以在位置匹配时调用,而不是使用 component 创建一个新的 React 元素。render 渲染方式接收所有与 component 方式相同的 route props

// 方便的内联渲染
<Route path="/home" render={() => <div>Home</div>} />

// 包装
const FadingRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    <FadeIn>
      <Component {...props} />
    </FadeIn>
  )} />
)

<FadingRoute path="/cool" component={Something} />

警告: 优先于 ,因此不要在同一个 中同时使用两者。

children: func

有时候不论 path 是否匹配位置,你都想渲染一些内容。在这种情况下,你可以使用 children 属性。除了不论是否匹配它都会被调用以外,它的工作原理与 render 完全一样。

children 渲染方式接收所有与 componentrender 方式相同的 route props,除非路由与 URL 不匹配,不匹配时 matchnull。这允许你可以根据路由是否匹配动态地调整用户界面。如下所示,如果路由匹配,我们将添加一个激活类:

const ListItemLink = ({ to, ...rest }) => (
  <Route path={to} children={({ match }) => (
    <li className={match ? 'active' : ''}>
      <Link to={to} {...rest} />
    </li>
  )} />
)

<ul>
  <ListItemLink to="/somewhere" />
  <ListItemLink to="/somewhere-else" />
</ul>

这对动画也很有用:

<Route children={({ match, ...rest }) => (
  {/* Animate 将始终渲染,因此你可以利用生命周期来为其子元素添加进出动画 */}
  <Animate>
    {match && <Something {...rest} />}
  </Animate>
)} />

警告:<Route component><Route render> 优先于 <Route children>,因此不要在同一个 <Route> 中同时使用多个。

Route props

三种渲染方式都将提供相同的三个路由属性:

  • match
  • location
  • history

match: object

const Topics = ({ match }) => (
  <div>
    <Link to={`${match.url}/rendering`}>Rendering with React</Link>
    <Route path={`${match.url}/:topicId`} component={Topic} />
  </div>
)

match 对象包含了 <Route path> 如何与 URL 匹配的信息,具有以下属性:

  • params: object 路径参数,通过解析 URL 中的动态部分获得键值对
  • isExact: bool 为 true 时,整个 URL 都需要匹配
  • path: string 用来匹配的路径模式,用于创建嵌套的
  • url: string URL 匹配的部分,用于嵌套的

在以下情境中可以获取 match 对象

  • 在 Route component 中,以 this.props.match 获取
  • 在 Route render 中,以 ({match}) => () 方式获取
  • 在 Route children 中,以 ({match}) => () 方式获取 uter 中,以 this.props.match 的方式获取 matchPath 的返回值

location: object

location 是指你当前的位置,将要去的位置,或是之前所在的位置

{
  key: 'ac3df4', // not with HashHistory!
  pathname: '/somewhere'
  search: '?some=search-string',
  hash: '#howdy',
  state: {
    [userDefined]: true
  }
}

在以下情境中可以获取 location 对象

  • Route component 中,以 this.props.location 获取
  • Route render 中,以 () => () 方式获取
  • Route children 中,以 () => () 方式获取
  • withRouter 中,以 this.props.location 的方式获取

可以在不同情境中使用 location:

<Link to={location} />
<NaviveLink to={location} />
<Redirect to={location />
history.push(location)
history.replace(location)

history: object

history 对象通常具有以下属性和方法:

  • length: number 浏览历史堆栈中的条目数
  • action: string 路由跳转到当前页面执行的动作,分为 PUSH, REPLACE, POP
  • location: object 当前访问地址信息组成的对象
  • push(path, [state]) 在历史堆栈信息里加入一个新条目。
  • replace(path, [state]) 在历史堆栈信息里替换掉当前的条目
  • go(n) 将 history 堆栈中的指针向前移动 n。
  • goBack() 等同于 go(-1)
  • goForward 等同于 go(1)
  • block(prompt) 阻止跳转

属性

path: string

可以是 path-to-regexp 能够理解的任何有效的 URL 路径。

<Route path="/users/:id" component={User} />

没有定义 path<Route> 总是会被匹配。【常用于搭建 404 页面】

exact: bool

如果为 true,则只有在 path 完全匹配 location.pathname 时才匹配。

<Route exact path="/one" component={OneComponent} />
// url: /one/two 不可以匹配到 OneComponent
// 若是没加 exact, 则路径为 /one/two 或 /one/two... 都可以匹配到该组件

strict: bool

如果为 true,则具有尾部斜杠的 path 仅与具有尾部斜杠的 location.pathname 匹配。当 location.pathname 中有附加的 URL 片段时,strict 就没有效果了。

<Route strict path="/one/" component={OneComponent} />
// url /one 不匹配
// url /one/ 或 /one/two 匹配

警告:可以使用 strict 来强制规定location.pathname 不能具有尾部斜杠,但是为了做到这一点,strictexact 必须都是 true

sensitive: bool

如果为 true,进行匹配时将区分大小写。

组件-Redirect

使用 <Redirect> 会导航到一个新的位置。新的位置将覆盖历史堆栈中的当前条目,例如服务器端重定向(HTTP 3xx)

import { Route, Redirect } from 'react-router-dom'

<Route
  exact
  path="/"
  render={() => (loggedIn ? <Redirect to="/dashboard" /> : <PublicHomePage />)}
/>

to: string

要重定向到的 URL,可以是 path-to-regexp 能够理解的任何有效的 URL 路径。所有要使用的 URL 参数必须由 from 提供。

<Redirect to="/somewhere/else" />

to: object

要重定向到的位置,其中 pathname 可以是 path-to-regexp 能够理解的任何有效的 URL 路径。

<Redirect
  to={{
    pathname: '/login',
    search: '?utm=your+face',
    state: {
      referrer: currentLocation
    }
  }}
/>

上例中的 state 对象可以在重定向到的组件中通过 this.props.location.state 进行访问。而 referrer 键(不是特殊名称)将通过路径名 /login 指向的登录组件中的 this.props.location.state.referrer进行访问。

push: bool

如果为 true,重定向会将新的位置推入历史记录,而不是替换当前条目。

<Redirect push to="/somewhere/else" />

from: string

要从中进行重定向的路径名,可以是 path-to-regexp 能够理解的任何有效的 URL 路径。所有匹配的 URL 参数都会提供给 to,必须包含在 to 中用到的所有参数,to 未使用的其它参数将被忽略。

只能在 <Switch>组件内使用 <Redirect from>,以匹配一个位置。

<Switch>
  <Redirect from="/old-path" to="/new-path" />
  <Route path="/new-path" component={Place} />
</Switch>
// 根据匹配参数进行重定向
<Switch>
  <Redirect from="/users/:id" to="/users/profile/:id" />
  <Route path="/users/profile/:id" component={Profile} />
</Switch>

译注:经过实践,发现以上“根据匹配参数进行重定向”的示例存在 bug,没有效果。to 中的 :id 并不会继承 from 中的 :id 匹配的值,而是直接作为字符串显示到浏览器地址栏!!!

exact: bool

strict: bool

// to为string
<Link to='/courses?sort=name'/>

// to为obj
<Link to={{
  pathname: '/courses',
  search: '?sort=name',
  hash: '#the-hash',
  state: { fromDashboard: true }
}}/>

// replace
<Link to="/courses" replace />
// replace(bool):为 true 时,点击链接后将使用新地址替换掉访问历史记录里面的原地址;
// 为 false 时,点击链接后将在原有访问历史记录的基础上添加一个新的纪录。默认为 false;
<NavLink to="/about" exact>About</NavLink>

<NavLink
  to="/faq"
  activeClassName="selected"
>FAQs</NavLink>

<NavLink
  to="/faq"
  activeStyle={{
    fontWeight: 'bold',
    color: 'red'
   }}
>FAQs</NavLink>

<NavLink
  to="/events/123"
  isActive={oddEvent}
>Event 123</NavLink>

参考