美文网首页
React Router学习之旅(二)

React Router学习之旅(二)

作者: LU7IN | 来源:发表于2017-12-17 00:14 被阅读0次
图片.png

我们给App添加的导航栏现在已经成功地显示在页面上了。不使用React Router,我们可以把ul做成一个组件,即Nav,然后把Nav渲染到我们的屏幕上。

你注意到你的应用像下图中那样相互嵌套在盒子里面吗?你注意到你的URLs变成像/repos/123这样了吗?我们组件的结构就如下图所示:

图片.png 图片.png 图片.png

React Router接受这样把路由给结合在一起,称为结合UI。

图片.png

分享我们的导航

让我们把AboutRepos组件给结合起来到App当中,并将其导航链接给分享至屏幕中去。我们需要做下面的两个步骤:

首先,让App的路由有子节点,并将其他的路由放到该子节点当中去。

index.js

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, hashHistory } from 'react-router'
import App from './modules/App'
import About from './modules/About'
import Repos from './modules/Repos'

render((
  <Router history={hashHistory}>
    <Route path="/" component={App}/>
    <Route path="/repos" component={Repos}/>
    <Route path="/about" component={About}/>
  </Router>
), document.getElementById('app'))

接着我们在App当中渲染该子节点。

moudules/App.js

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

export default React.createClass({
  render() {
    return (
      <div>
        <h1>React Router Tutorial</h1>
        <ul role="nav">
          <li><Link to="/about">About</Link></li>
          <li><Link to="/repos">Repos</Link></li>
        </ul>
        {this.props.children}
      </div>
    )
  }
})
图片.png

好了,现在点击链接而且注意到App会持续得渲染子路由组件通过this.props.children

图片.png

有一种方法可以让Link区别于a,那就是让链接可以动态地更换自身的风格。

让我们看看如何用内联的方法,添加activeStyle到你的Link上。

modules/App.js

<li><Link to="/about" activeStyle={{ color: 'red' }}>About</Link></li>
<li><Link to="/repos" activeStyle={{ color: 'green' }}>Repos</Link></li>
图片.png

现在我们只要用鼠标点击一下,导航栏就会变成红色了的。

图片.png

我们同样可以使用Class Name

modules/App.js

我们不必将样式写在该页面上去。让我们添加一个额外的link标签。

index.html

<link rel="stylesheet" href="index.css">

图片.png

效果如图所示:

图片.png 图片.png

网站中的大多数的链接不必知道他们是否是活跃的,通常只有主要的链接是需要知道的而已。将那些你不必去记住的activeClassNameactiveStyle给包裹起来。

我们将使用一个展开的操作器,也就是三个点。使用这种方法,它会克隆我们的属性activeClassName到我们想要的组件。

创建一个文件为NavLink.js在modules文件目录下。

NavLink.js

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

export default React.createClass({
  render() {
    return <Link {...this.props} activeClassName="active"/>
  }
})
图片.png

接着我们将链接换成NavLink

modules/App.js

import React from 'react'
import { Link } from 'react-router'
import NavLink from './NavLink'

export default React.createClass({
  render() {
    return (
      <div>
        <h1>React Router Tutorial</h1>
        <ul role="nav">
           <li><NavLink to="/about">About</NavLink></li>
           <li><NavLink to="/repos">Repos</NavLink></li>
        </ul>
      </div>
    )
  }
})
图片.png

现在我们点击这两个链接并不会直接跳转。

图片.png

URL参数

考虑下面的URL,如上图所示。

这些URL会匹配路由的路径,比如:

/repos/:userName/:repoName

参数是从:开始的:这些URL参数将会被解析以及变为可以访问的路由组件通过this.props.params[name]

图片.png

给路由添加参数

让我们的应用在屏幕上去如何渲染/repos/:userName/:repoName

首先我们需要一个组件去渲染这个路由,新建一个文件夹modules/Repo.js:

代码如下:

Repo.js

import React from 'react'

export default React.createClass({
  render() {
    return (
        <div>
           <h2>{this.props.params.repoName}</h2>
        </div>
        )
  }
})

index.js

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, hashHistory } from 'react-router'
import App from './modules/App'
import About from './modules/About'
import Repos from './modules/Repos'
import Repo from './modules/Repo'

render((
  <Router history={hashHistory}>
    <Route path="/" component={App}>
      <Route path="/repos" component={Repos}/>
      <Route path="/repos/:userName/:repoName" component={Repo}/>
      <Route path="/about" component={About}/>
    </Route>
  </Router>
), document.getElementById('app'))

Repos.js

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

export default React.createClass({
  render() {
    return (
        <div>
           <h2>Repos</h2>

           <ul>
              <li><Link to="/repos/reactjs/react-router">React Router</Link></li>
              <li><Link to="/repos/facebook/react">React</Link></li>
           </ul>
        </div>
        )
  }
})
图片.png

现在路由路径的参数名称已经变成组件的属性了。repoNameuserName已经可以组件中通过this.props.params来访问到。

图片.png

注意,当我们导航到不同的仓库时,其他的导航链接是如何消失的?

首先,将Repo路由给聚集到Repos路由下。然后在Reposthis.props.children渲染。

图片.png 图片.png 图片.png

动态链接

让我们把active属性添加到NavLink上。

modules/Repos.js

import React from 'react'
import { Link } from 'react-router'
import NavLink from './NavLink'

export default React.createClass({
  render() {
    return (
      <div>
        <h2>Repos</h2>
        <ul>
          <li><NavLink to="/repos/reactjs/react-router">React Router</NavLink></li>
          <li><NavLink to="/repos/facebook/react">React</NavLink></li>
        </ul>

        {this.props.children}
      </div>
    )
  }
})
图片.png 图片.png

索引路由

当我们通过/访问一个空白的界面,我们想要渲染一个Home组件在这个空白的界面。我们创建这个组件并试着如何去渲染它。

代码太多我就偷懒不贴上来了,看图就好:

图片.png 图片.png 图片.png

打开localhost:8080,显示如下:

图片.png

IndexRoute我看得不是很懂,所以下面的内容我是搬运阮一峰老师的:

下面的例子,你会不会觉得有一点问题?

    <Router>
      <Route path="/" component={App}>
        <Route path="accounts" component={Accounts}/>
        <Route path="statements" component={Statements}/>
      </Route>
    </Router>

上面代码中,访问根路径/,不会加载任何子组件。也就是说,App组件的this.props.children,这时是undefined

因此,通常会采用{this.props.children || <Home/>}这样的写法。这时,Home明明是AccountsStatements的同级组件,却没有写在Route中。

IndexRoute就是解决这个问题,显式指定Home是根路由的子组件,即指定默认情况下加载的子组件。你可以把IndexRoute想象成某个路径的index.html

    <Router>
      <Route path="/" component={App}>
        <IndexRoute component={Home}/>
        <Route path="accounts" component={Accounts}/>
        <Route path="statements" component={Statements}/>
      </Route>
    </Router>

现在,用户访问/的时候,加载的组件结构如下。

    <App>
      <Home/>
    </App>

这种组件结构就很清晰了:App只包含下级组件的共有元素,本身的展示内容则由Home组件定义。这样有利于代码分离,也有利于使用React Router提供的各种API。

注意,IndexRoute组件没有路径参数path

总结一下,IndexRoute就是默认加载显示的那个组件。

相关文章

网友评论

      本文标题:React Router学习之旅(二)

      本文链接:https://www.haomeiwen.com/subject/pwvewxtx.html