React-Router v4

说到 React 我们一定离不开和 Router 打交道。不管 Vue Router 和 React Router ,他们的原理都是差不多的。这篇文章会从一个简单的例子一直拓展到真正的 React Router。

React-router

React Router 是专为 React 设计的路由解决方案。它利用HTML5 的history API,来操作浏览器的 session history (会话历史)。

React 路由

React Router被拆分成四个包:

  • react-router 实现了路由的核心功能。
  • react-router-dom 基于react-router,加入了在浏览器运行环境下的一些功能。
  • react-router-native 基于react-router,加入了 React Native 运行环境下的一些功能
  • react-router-redux React Router 和 Redux 的集成
  • react-router-config

react-router提供核心的路由组件与函数。react-router-config用来配置静态路由(还在开发中。

进行网站(将会运行在浏览器环境中)构建,我们应当安装react-router-dom。因为react-router-dom已经暴露出react-router中暴露的对象与方法,因此你只需要安装并引用react-router-dom即可。

安装

如上所说,我们使用react开发web应用,所以只需要安装react-router-dom。

  npm install react-router-dom --save

理解和使用react-router

  • BrowserRouter,这是对Router接口的实现。使得页面和浏览器的history保持一致。如:window.location
  • HashRouter,和上面的一样,只是使用的是url的hash部分,比如:window.location.hash
  • MemoryRouter
  • NativeRouter,处理react native内的路由。
  • StaticRouter,处理静态路由,和v3一样。

BrowserRouter vs HashRouter

在react-router的各种router中,<BrowserRouter><HashRouter>是可以在浏览器中使用的。如果你使用的是一个非静态的站点、要处理各种不同的url那么你就需要使用BrowserRouter。相反的如果你的server只处理静态的url,那么就使用HashRouter

理解和使用Router

在4.0之前版本的 API 中,<Router> 组件的 children 只能是 React Router 提供的各种组件,如<Route><IndexRoute><Redirect>等。而在 React Router 4 中,你可以将各种组件及标签放进 <Router>组件中,他的角色也更像是 Redux 中的 <Provider>。不同的是<Provider>是用来保持与 store 的更新,而<Router>是用来保持与 location 的同步.

// 示例1
<Router>
    <div>
      <ul>
        <li><Link to="/">首页</Link></li>
        <li><Link to="/about">关于</Link></li>
        <li><Link to="/topics">主题列表</Link></li>
      </ul>

      <hr/>

      <Route exact path="/" component={Home}/>
      <Route path="/about" component={About}/>
      <Route path="/topics" component={Topics}/>
    </div>
  </Router>

Router是所有路由组件共用的底层接口,一般我们的应用并不会使用这个接口,而是使用高级的路由:

  • <BrowserRouter>:这是一个路由管理器,使用 HTML5 提供的 history API 来保持 UI 和 URL 的同步;
  • <HashRouter>:使用 URL 的 hash (例如:window.location.hash) 来保持 UI 和 URL 的同步;
  • <MemoryRouter>:能在内存保存你 “URL” 的历史纪录(并没有对地址栏读写);
  • <NativeRouter>:为使用React Native提供路由支持;
  • <StaticRouter>:从不会改变地址;

理解和使用Route

<Route>组件是react router v4里最有用的组件。背后的使用哲学也很简单,无论何时你需要在匹配某个路径的时候绘制一个组件,那么就可以使用Route组件。

Route组件可以使用如下的属性:

  • path属性,字符串类型,它的值就是用来匹配url的。
  • component属性,它的值是一个组件。在path匹配成功之后会绘制这个组件。
  • exact属性,为true时,则要求路径与location.pathname必须完全匹配。
  • strict属性,为true的时候,有结尾斜线的路径只能匹配有斜线的location.pathname。

还有其他的一些属性,可以用来代替component属性。

  • render属性,一个返回React组件的方法。传说中的rencer-prop就是从这里来的。
  • children属性,返回一个React组件的方法。只不过这个总是会绘制,即使没有匹配的路径的时候。

多数的时候是用component属性就可以满足。但是,某些情况下你不得不使用renderchildren属性。

  • match
  • location
  • history
const FadingRoute = ({ component, ...rest }) => (
  <Route {...rest} render={(props) => (
    <FadeIn>
      <componnet {...props} />
    </FadeIn>
  )} />
)

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

    <Route path="/news" component={NewsFeed}/>

    <Route path="/user" render={()=><div>UserPage</div>} />

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

  </div>
</Router>

// <Route component>的优先级要比<Route render>高,所以不要在同一个<Route>中同时使用这两个属性

exact配置:

路径 location.pathname exact 是否匹配
/my /my/one true
/my /my/one false

strict配置:

路径 location.pathname strict 是否匹配
/my/ /my true
/my/ /my/ true
/my/ /my/one true

使用Link可以在React应用的不同页面之间跳转。与unclor会重新加载整个页面不同,Link只会重新加载页面里和当前url可以匹配的部分。

  • to(string/object):要跳转的路径或地址;
  • replace(bool):为 true 时,点击链接后将使用新地址替换掉访问历史记录里面的原地址;为 false 时,点击链接后将在原有访问历史记录的基础上添加一个新的纪录。默认为 false;
import { Link } from 'react-router-dom';

<Link to={{
  pathname: '/me',
  search: '?sort=asc',
  hash: '#hash',
  state: { fromHome: true }
}} />

实例:

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

const Nav = () => (
  <Link to='/'>Home</Link>
  <Link to="/about">About</Link>
  <Link to="/other">Other</Link>
  <Link to="/user">User</Link>
  <Link to="/my">My</Link>

  // 禁止跳转
<Link to='##'>Home</Link>  // 意想不到的效果
);

NavLinkLink的一个子类,在Link组件的基础上增加了绘制组件的样式,比如:

  • activeClassName(string):设置选中样式,默认值为 active;
  • activeStyle(object):当元素被选中时, 为此元素添加样式;
  • exact(bool):为 true 时, 只有当地址完全匹配 class 和 style 才会应用;
  • strict(bool):为 true 时,在确定位置是否与当前 URL 匹配时,将考虑位置 pathname 后的斜线;
  • isActive(func):判断链接是否激活的额外逻辑的功能;
// activeClassName选中时样式为selected
<NavLink
  to="/faq"
  activeClassName="selected"
>FAQs</NavLink>

// 选中时样式为activeStyle的样式设置
<NavLink
  to="/faq"
  activeStyle={{
    fontWeight: 'bold',
    color: 'red'
   }}
>FAQs</NavLink>

// 当event id为奇数的时候,激活链接
const oddEvent = (match, location) => {
  if (!match) {
    return false
  }
  const eventID = parseInt(match.params.eventID)
  return !isNaN(eventID) && eventID % 2 === 1
}

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

Switch的用法

组件和语法中的 switch 功能类似,执行第一个匹配的路由。这个逻辑很直观也就是排他性,主要解决使用多个 <Route> 时多个路由同时匹配的问题。
<Switch>的独特之处是独它仅仅渲染一个路由。相反地,每一个包含匹配地址(location)的<Route>都会被渲染。
实例:

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

如果现在的URL是/about,那么, , 还有都会被渲染,因为它们都与路径(path)匹配。这种设计,允许我们以多种方式将多个组合到我们的应用程序中,例如侧栏(sidebars),面包屑(breadcrumbs),bootstrap tabs等等。 然而,偶尔我们只想选择一个来渲染。如果我们现在处于/about,我们也不希望匹配/:user(或者显示我们的 “404” 页面 )。以下是使用 Switch 的方法来实现:

<Switch>
  <Route exact path="/" component={Home}/>
  <Route path="/about" component={About}/>
  <Route path="/:user" component={User}/>
  <Route component={NoMatch}/>
</Switch>

使用Redirect组件实现重定向

无论何时你要重定向到另外一个地址的时候,都可以使用Redirect组件:

<Redirect to="register" />

浏览器历史

react router v4中,提供了一个history对象。这个对象包含了多个api,可以用来操作浏览器历史等。

你也可以在React应用里使用history对象的方法:

goMy = () => {
this.props.history.push("/my")
}
render() {
    return <div onClick={this.goMy}>我的</div>
}

用另外的方法可以写成:

<Link to="/my" />
<Redirect to="my" />

使用react router dom实现你的第一个demo

现在我们用react router dom来实现第一个demo。

首先,引入必要的组件。比如:RouteBrowserRouter

写App组件

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

const App = () => (
  <BrowserRouter>
    <BaseLayout />
  </BrowserRouter>
)

render(<App />, document.getElementById('root'));

我们来已创建的组件:

const BaseLayout = () => (
  <div className="base">
    <header>
      <p>React Router v4 Browser Example</p>
      <nav>
        <ul>
          <li><Link ="/">Home</Link></li>
          <li><Link ="/about">About</Link></li>
          <li><Link ="/me">Profile</Link></li>
          <li><Link ="/login">Login</Link></li>
          <li><Link ="/register">Register</Link></li>
          <li><Link ="/contact">Contact</Link></li>
        </ul>
      </nav>
    </header>
    <div className="container">
      <Route path="/" exact component={HomePage} />
      <Route path="/about" component={AboutPage} />
      <Route path="/contact" component={ContactPage} />
      <Route path="/login" component={LoginPage} />
      <Route path="/register" component={RegisterPage} />
      <Route path="/me" component={ProfilePage} />
    </div>
    <footer>
      React Router v4 Browser Example (c) 2017
    </footer>
  </div>
);

同时我们用react router v4里的Link和NavLink组件。

const BaseLayout = () => (
  <div className="base">
    <header>
      <p>React Router v4 Browser Example</p>
      <nav>
        <ul>
          <li><Link ="/">Home</Link></li>
          <li><Link ="/about">About</Link></li>
          <li><Link ="/me">Profile</Link></li>
          <li><Link ="/login">Login</Link></li>
          <li><Link ="/register">Register</Link></li>
          <li><Link ="/contact">Contact</Link></li>
        </ul>
      </nav>
    </header>
    <div className="container">
      <Route path="/" exact component={HomePage} />
      <Route path="/about" component={AboutPage} />
      <Route path="/contact" component={ContactPage} />
      <Route path="/login" component={LoginPage} />
      <Route path="/register" component={RegisterPage} />
      <Route path="/me" component={ProfilePage} />
    </div>
    <footer>
      React Router v4 Browser Example (c) 2017
    </footer>
  </div>
);

参考地址:

react router 4;
Run丘比特-掘金;


   转载规则


《React-Router v4》 echo丶若梦 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
什么是类?(class) 什么是类?(class)
类(class)是在 JS 中编写构造函数的新方法。它是使用构造函数的语法糖,在底层中使用仍然是原型和基于原型的继承。 //ES5 Version function Person(firstName, lastName, age
2020-01-14
下一篇 
JS数组reduce() JS数组reduce()
1、语法reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。 reduce() 可以作为一个高阶函数,用于函数的 compose。 注意: reduce() 对于空数组是不会执行回调函数的
2020-01-07
  目录