react学习笔记(二)react-router V4.0的使用

353 阅读7分钟

本文主要讲述react-router 4.0的常用方式和基础api

接入react-router

使用create-react-app创建好项目之后

$ # web项目安装react-router-dom依赖
$ npm i react-router-dom

src/app.tsx使用react-router

首先展示一下基本使用示例

src/app.tsx

import React from 'react';
import { BrowserRouter as Router,Route, Link } from 'react-router-dom'
import './App.css';

//Home组件
const Home:React.FC = ()=>{
  return (
    <div>Home</div>
  )
}

//List组件
const List:React.FC = ()=>{
  return (
    <div>List</div>
  )
}

class App extends React.Component{
  render() {
    return (
      <div className="App">
        <Router>
        <div>
          <p><Link to="/">Home</Link></p>
          <p><Link to="/list">List</Link></p>
        </div>
          <Route exact path='/' component={Home} />
          <Route path='/list' component={List} />
        </Router>
      </div>
    );
  }
}

export default App;

下面是react-router的一些常用组件

BrowserRouter

使用HTML5历史记录API(pushState,replaceState和popstate事件)的来保持UI与URL同步。

<BrowserRouter
basename={optionalString}
forceRefresh={optionalBool}
getUserConfirmation={optionalFunc}
keyLength={optionalNumber} >
<App/>
</BrowserRouter>
  • 属性:

    • basename: string

    所有locations的基本URL。如果应用程序从服务器上的子目录提供,则需要将其设置为子目录。正确格式的基础名称应该有一个主要的斜杠,但没有尾部斜线

    <BrowserRouter basename="/calendar"/>
    <Link to="/today"/> 
    
    //如此匹配到的路由是:'/calendar/today'
    
    • getUserConfirmation: (message:string,callback:(allowTransition:boolean)=>void)=>void

    用于确认导航的功能。默认使用window.confirm,要配合组件使用

    const getConfirmation = (message, callback) => {
        const allowTransition = window.confirm(message)
        callback(allowTransition)
    } 
    <BrowserRouter getUserConfirmation={getConfirmation}/>
    
    • forceRefresh: boolean

    如果为true,则路由器将在页面导航中使用全页刷新。 使用场景:在不支持HTML5历史记录API的浏览器中使用此功能

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

    location.key的长度。默认为6。

    <BrowserRouter keyLength={12}/>
    

HashRouter

使用URL的哈希部分(即window.location.hash)的来保持UI与URL同步。

Hash history不支持location.key或location.state。

由于此技术仅用于支持旧版浏览器,因此建议将服务器配置为使用

import { HashRouter } from 'react-router-dom'

<HashRouter>
<App/>
</HashRouter>
  • 属性

    • basename (同BrowserHistory)

    • getUserConfirmation(同BrowserHistory)

    • hashType: string 用于window.location.hash的编码类型。可用值为(默认值"slash"):

      • "slash": 创建一个hash值,例如:#/ and #/sunshine/lollipops

      • "noslash": 创建一个hash值,例如:# and #sunshine/lollipops

      • ”hashbang“: 创建一个”ajax crawlable” (已被谷歌弃用) 例如:#!/ and #!/sunshine/lollipops

Link

路由跳转组件

如下代码点击Link组件将跳转至路由:'/about'

import { Link } from 'react-router-dom'

<Link to="/about">About</Link>

  • to: string | object

链接到的路径名或位置。

<Link to="/courses"/>
// or

//该方法会在组件的props.location上追加相应的属性
<Link to={{
pathname: '/courses', //路由
search: '?sort=name', //params
hash: '#the-hash',  //hash值
state: { fromDashboard: true } //state
}}/>
  • replace: boolean

如果为true,单击链接将替换历史堆栈中的当前条目,而不是添加新条目。

<Link to="/courses" replace />

NavLink

一种特殊版本的,当与当前URL匹配时,将向渲染元素添加样式属性。

import { NavLink } from 'react-router-dom'

<NavLink to="/about">About</NavLink>

属性

  • activeClassName: string 当前路由的class类名
<NavLink
to="/faq" activeClassName="selected"
>FAQs</NavLink>
  • activeStyle: object

当元素处于活动状态时应用于元素的样式。

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

只有完全匹配当前path的时候才会触发活动状态

//只有路由是'/'的时候才会匹配,'/a'不会被匹配
<NavLink exact to="/" >Profile</NavLink>
  • strict: boolean 当为真时,在确定位置是否与当前网址匹配时,将考虑位置路径名上的尾部斜线。
//如果在浏览器中输入''
<NavLink strict to="/events/" >Events</NavLink>

Redirect

渲染将导航到新位置。新位置将覆盖历史堆栈中的当前位置,如服务器端重定向(HTTP 3xx)。

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

<Route exact path="/" render={() => (
loggedIn ? ( <Redirect to="/dashboard"/>
) : ( <div>其他组件</div>)}/>

属性:

- to: string

要重定向到的地址。

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

- to: object

要重定向到的地址。

<Redirect to={{
pathname: '/login',  //重定向的路由
search: '?utm=your+face',  //路由参数(props.loaction.search)
state: { referrer: currentLocation }  //往props.location.state上追加参数
}}/>

- push: boolean

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

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

- from: string

只有当当前的路由是from的时候才会重定向到to路由

<Switch>
<Redirect from='/old-path' to='/new-path'/>
<Route path='/new-path' component={Place}/>
</Switch>

Route

路由组件可能是React Router中了解和学习使用的最重要的组件。其最基本的责任是在位置与路线的路径匹配时呈现一些UI。

import { BrowserRouter as Router, Route } from 'react-router-dom'

//Home组件
const Home = (props)=>(<div>Home</div>)

//List组件
const List= (props)=>(<div>list</div>)

<Router>
    <div>
        <Route exact path="/" component={Home}/>
        <Route path="/list" component={List}/>
    </div>
</Router>
<Home/>

Route render methods

有3种方法可以使用呈现某些东西:

  • 仅当位置匹配时才呈现的React组件.它将与route props一起呈现。

    当您使用组件(而不是下面的渲染或子项)时,路由器使用React.createElement从给定组件创建一个新的React元素。 这意味着如果您向组件属性提供内联函数,则可以在每个渲染中创建一个新组件.这将导致现有组件卸载和新组件安装,而不是仅更新现有组件 当使用内联函数进行内联渲染时,请使用render或child(下文)

    <Route path="/user/:username" component={User}/>
    const User = ({ match }) => { return <h1>Hello {match.params.username}!</h1>
    }
    
  • Route render

    这允许方便的在线呈现和包装,而不需要上述的不期望的重新安装。您可以使用组件支持为您创建一个新的React元素,而不必在位置匹配时传入要调用的函数。 渲染道具接收与组件渲染道具相同的所有route props。

    警告:取决于,所以不要在同一个中使用两者

    // 内联呈现
     <Route path="/home" render={() => <div>Home</div>}/>
        
     // 包装/合成
     //component:Component,取别名的意思
     const FadingRoute = ({ component: Component, ...rest }) => ( 
      <Route {...rest} render={props => (
          <FadeIn>
              <Component {...props}/>
          </FadeIn>
      )}/>
     ) 
     <FadingRoute path="/cool" component={Something}/>
    
  • Route children

有时您需要渲染路径是否匹配该位置。在这些情况下,可以使用函数child prop。它的工作原理就像渲染,除了它被调用是否有匹配 children 渲染prop接收与组件和渲染方法相同的所有route props,除非路由未能匹配URL,则match为null。 这允许您根据路线是否匹配来动态调整用户界面。

例如我们做一个简单的路由转场动画


//Home组件
const Home: React.FC = (props) => {
  return (
    <div className="page">home</div>
  )
}

//List组件
const List: React.FC = (props) => {
  return (
    <div className="page">list</div>
  )
}

const WrapAnimation = ({ component: Component,...rest }) => {
  console.log(rest.match)
  return (
    <CSSTransition
      in={rest.match !== null}
      classNames={{
        enter: 'animated',
        enterActive: 'fadeInLeft',
        exit: 'animated',
        exitActive: 'fadeOut'
      }}
      timeout={1000}
      mountOnEnter={true}
      unmountOnExit={true}
    >
      <div style={{position:'fixed',left:0,top:'30px',width:'100%'}}>
        <Component {...rest} />
      </div>
    </CSSTransition>
  )
}

<Router>
  <div>
    <Link to="/" >home</Link>
    <Link to="/list">list</Link>
  </div>
  <Route path='/' exact children={(props) => {
    return (
      <WrapAnimation component={Home} {...props} />
    )
  }} />
  <Route path='/list' children={(props) => {
    return (
      <WrapAnimation component={List} {...props} />
    )
  }} />
</Router>

警告:和优先级高于,所以不要在同一个中使用多个.

每个在不同的情况下都有用。您只能在给定的上使用这些方法之一。请看下面的解释,了解为什么你有3个选项。大多数时候你会使用component。

Route props

所有三个渲染方法将通过相同的三个route props

  • match
  • location
  • history

withRouter

您可以通过withRouter高阶组件访问历史对象的属性和最接近的的匹配。随着路由每次路由改变时,路由器会重新渲染其组件,路径与<路径>渲染道具:{match,location,history}相同。

import { withRouter } from 'react-router'

//let NewComponent = withRouter(OldComponent)

const Test= withRouter((props)=>{
  console.log(props,123)
  return (
    <div>123</div>
  )
})

//普通组件也能拿到location,match,history等props