React Router笔记 -- 摘自阮一峰大神博客

React-Router是React体系中的路由库,它通过管理URL,实现组件的切换和状态的变化。

基本用法

Router是一个React组件:

import { Router } from 'react-router';
render(<Router/>,document.getElementById('app'));

Router组件本身只是一个容器,真正的路由要通过Route组件定义:

import { Router,Route,hashHistory } from 'react-router';

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

上面的代码表示,如果用户访问根路由 + “/”,组件(component={App})APP就会加载到:document.getElementById('app'))

注:
上面的例子中,Router组件有一个参数history,它的值hashHistory表示,路由的切换由URL的hash变化决定,即URL的#部分发生变化。举例来说,用户访问http://www.example.com/,实际会看到的是http://www.example.com/#/

一个稍微复杂的例子:

<Router history={hashHistory}>
  <Route path="/" component={App}/>
  <Route path="/repos" component={Repos}/>
  <Route path="/about" component={About}/>
</Router>

代码解释:
用户访问/repos,则加载Repos组件,访问/about,则加载About组件。

嵌套路由

组件Route可以嵌套。

<Router history={hashHistory}>
  <Route path="/" component={App}>
    <Route path="/repos" component={Repos}/>
    <Route path="/about" component={About}/>
  </Route>
</Router>

嵌套的组件表示,用户访问/repos时,会先加载App组件,然后在它的内部再加载Repos组件。

<App>
  <Repos/>
</App>

当Router下面的字路由比较多的时候,我们可以写成这样的形式:

let routes = <Route path="/" component={App}>
  <Route path="/repos" component={Repos}/>
  <Route path="/about" component={About}/>
</Route>;

<Router routes={routes} history={browserHistory}/>

Route的path属性

Route组件的Path指定路由的匹配规则。这个属性可以省略。

并且,path属性可以使用通配符。

规则如下:

1、paramName
    :paramName匹配URL一个部分,直到遇到下一个/、?、#为止。这个路径参数可以通过this.props.params.paramName取出。
2、()
    ()表示URL的这个部分是可选的。
3、*
    *匹配任意字符,直到模式里面的下一个字符为止。匹配方式是非贪婪模式。
4、**
    ** 匹配任意字符,直到下一个/、?、#为止。匹配方式是贪婪模式。

例子:

<Route path="/hello/:name">
// 匹配 /hello/michael
// 匹配 /hello/ryan

<Route path="/hello(/:name)">
// 匹配 /hello
// 匹配 /hello/michael
// 匹配 /hello/ryan

<Route path="/files/*.*">
// 匹配 /files/hello.jpg
// 匹配 /files/hello.html

<Route path="/files/*">
// 匹配 /files/ 
// 匹配 /files/a
// 匹配 /files/a/b

<Route path="/**/*.jpg">
// 匹配 /files/hello.jpg
// 匹配 /files/path/to/file.jpg

path属性也可以使用相对路径,也就是不以 / 开头。这是,匹配的路径就会相对于父组件的路径。

路由匹配是从上到下执行的,一旦发现匹配,就不会继续向下查找其他的规则了。

IndexRoute组件

看这个栗子:

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

这个栗子存在这一个问题:如果我们访问路径 / ,不会加载任何子组件。也就是说,App组件的this.props.children是undefined。

IndexRoute就是为了解决这个问题,显式指定 Home 是根路由的子组件,即指定认情况下加载的子组件。

我们把上面的代码改成:

<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组件定义。这样有利于代码分离。

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

Redirect组件

Redirect组件用于路由的跳转,即用户访问一个路由,会自动跳转到另一个路由。

<Route path="inBox" component={InBox}>
  {/* 从 /inBox/messages/:id 跳转到 /messages/:id */}
  <Redirect from="messages/:id" to="/messages/:id" />
</Route>

现在,如果用户访问/inBox/messages/5,就会自动跳转到/messages/5。

IndexRedirect组件

该组件用于访问根路由的时候,将用户重定向到某个子组件。

<Route path="/" component={App}>
  <IndexRedirect to="/welcome" />
  <Route path="welcome" component={Welcome} />
  <Route path="about" component={About} />
</Route>

上面代码中,如果用户访问根路径,将自动重定向到子组件welcome。

Link

Link组件用于取代 a 元素,生成一个连接,允许用户点击后跳转到另一个路由,它基本上就是a元素的React版本,可以接收Router状态。

render() {
  return <div>
    <ul role="nav">
      <li><Link to="/about">About</Link></li>
      <li><Link to="/repos">Repos</Link></li>
    </ul>
  </div>
}

Link组件有一个activeStyle属性,可以定义当前用户的样式。

<Link to="/about" activeStyle={{color: 'red'}}>About</Link> <Link to="/repos" activeStyle={{color: 'red'}}>Repos</Link>

现在,这个链接将会显式红色。

还有一种方式是定义属性activeClassName为这个路由添加class

<Link to="/about" activeClassName="active">About</Link>
<Link to="/repos" activeClassName="active">Repos</Link>

IndexLink

如果想要链接到根路由,需要使用IndexLink组件。

这是因为,对于根路由来说,activeStyle 和 activeClassName 会失效,或者说总是生效,因为 / 会匹配任何子路由。而IndexLink组件会使用路径的精确匹配。

另一种方式是使用Link组件的onlyActiveOnIndex属性

<Link to="/" activeClassName="active" onlyActiveOnIndex={true}>
  Home
</Link>

history 属性

Router组件的history属性,用来监听浏览器地址栏的变化,并将URL解析成一个地址对象,供React Router匹配。

history属性可以设置三种值:

browserHistory
hashHistory
createMemoryHistory

browserHistory:路由将通过URL的hash部分切换。

browserHistory:路由将采用正常的路径。

createMemoryHistory:用于服务器渲染。

表单处理

表单和React Router的对接方法

<form onSubmit={this.handleSubmit}>
  <input type="text" placeholder="userName"/>
  <input type="text" placeholder="repo"/>
  <button type="submit">Go</button>
</form>

方法1,使用browserHistory.push

import { browserHistory } from 'react-router'

// ...
  handleSubmit(event) {
    event.preventDefault()
    const userName = event.target.elements[0].value
    const repo = event.target.elements[1].value
    const path = `/repos/${userName}/${repo}`
    browserHistory.push(path)
  },

方法2,使用context对象

export default React.createClass({

  // ask for `router` from context
  contextTypes: {
    router: React.PropTypes.object
  },handleSubmit(event) {
    // ...
    this.context.router.push(path)
  },})

路由的钩子

每个路由都有Enter和Leave钩子,用户进入或者离开该路由的时候会触发。

<Route path="about" component={About} />
<Route path="inBox" component={InBox}>
  <Redirect from="messages/:id" to="/messages/:id" />
</Route>

上面的代码中,如果用户离开/messages/:id,进入/about时,会依次触发以下的钩子。

/messages/:id的onLeave /inBox的onLeave /about的onEnter

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom