react-router-dom入门基本使用

快速入门

下载安装

## 安装 react 脚手架并创建项目
npm install -g create-react-app
create-react-app demo-app
cd demo-app

## 安装 react-router-dom
## or, if you're not using yarn
## yarn add react-router-dom 
npm install react-router-dom

进入项目修改App.js

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

const Home = () => (
  <div>
    <h2>Home</h2>
  </div>
)

const About = () => (
  <div>
    <h2>About</h2>
  </div>
)

const Topic = ({ match }) => (
  <div>
    <h3>{match.params.topicId}</h3>
  </div>
)

const Topics = ({ match }) => (
  <div>
    <h2>Topics</h2>
    <ul>
      <li>
        <Link to={`${match.url}/rendering`}>
          Rendering with React
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/components`}>
          Components
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/props-v-state`}>
          Props v. State
        </Link>
      </li>
    </ul>

    <Route path={`${match.path}/:topicId`} component={Topic}/>
    <Route exact path={match.path} render={() => (
      <h3>Please select a topic.</h3>
    )}/>
  </div>
)

const App = () => (
  <Router>
    <div>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
        <li><Link to="/topics">Topics</Link></li>
      </ul>
      <hr/>
      <Route exact path="/" component={Home}/>
      <Route path="/about" component={About}/>
      <Route path="/topics" component={Topics}/>
    </div>
  </Router>
)
export default App

启动项目npm start
浏览器输入:http://localhost:3000/
观察到以下页面表示使用router成功
在这里插入图片描述
可以在App.js中看到,react-router-dom中,引入了BrowserRouterRouteLink三个组件,下面开始分别介绍。

Link

使用该组件可以编写路由路径path,改变浏览器地址栏的路径,基本语法

<Link to="/">Home</Link>

to属性:链接位置的字符串表示,还可以是一个对象

<Link to={{
  pathname: '/courses',						#pathname: 表示要链接到的路径的字符串。
  search: '?sort=name',						#search: 表示查询参数的字符串形式。
  hash: '#the-hash',						#放入网址的 hash,例如 #a-hash。
  state: { fromDashboard: true }			#状态持续到 location。
}}/>

还有一个比较常用的属性replace,如果为 true,则单击链接将替换历史堆栈中的当前入口,而不是添加新入口。
react-router-dom是基于浏览器的history对象来进行操作的,该对象使用栈数据结构维护历史记录,当点击一个新的链接时,就将该链接入栈,如果replace属性为true,点击时总是替换history对象的栈顶链接。

Route

使用该组件可以对上面Link编写好的路由路径进行注册,并设置路径对应要展示的组件。注册的路由在进行匹配时,是从上到下按顺序匹配的,若没有Switch包裹,无论有多少个Route都进行一遍扫描匹配。
文档原话:它最基本的职责是在 location 与 Route 的 path 匹配时呈现一些 UI。

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

常用属性:
exact:如果为 true,则只有在路径完全匹配时才匹配。默认模糊匹配,即浏览器地址只有前面部分完美匹配时才显示,如浏览器为 /about/a/b/c,而Route为 /about,可以匹配成功,两者反之则不行。
path:任何可以解析的有效的 URL 路径,一般对应Link的to属性
component:只有当位置匹配时才会渲染的 React 组件。
render:与component作用相同,该方式使用内联编写,而不引用外部暴露的 React 组件。render的类型是function,Route会渲染这个function的返回值。因此它的作用就是附加一些额外的逻辑
sensitive:如果路径区分大小写,则为 true ,则匹配。

BrowserRouter

包裹LinkRoute的组件,使得UI组件与地址URL保持同步,若LinkRoute不被BrowserRouter包裹,则会报错。另外,Link编写的好的路径,在注册时,LinkRoute必须要在同一个BrowserRouter内才会起作用,不能分开在不同的BrowserRouter。通常可以像上面的例子一样,直接在index.js中包含<App/>组件使用。

<BrowserRouter basename={optionalString}>
  <App/>
</BrowserRouter>

basename:所有地址的基本网址。如果您的应用程序是从服务器上的子目录提供的,则需要将其设置为子目录。格式正确的基本名应该有一个前导斜线,但是结尾不能有斜线。

<BrowserRouter basename="/calendar"/>
<Link to="/today"/> // renders <a href="/calendar/today">

react-router-dom还有一个组件与BrowserRouter有同样的作用,HashRouter。与之不同,HashRouter会在路径后面添加一个#号,如

<HashRouter basename="/calendar"/>
<Link to="/today"/> // renders <a href="#/calendar/today">

#后面的字符不会发送到后台服务器。


拓展NavLink

该组件也是react-router-dom里的组件,是Link的升级版,当点击导航Link的时候,会动态给所点击的组件加类名,如

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

activeClassName:NavLink默认的加的类名就是"active",这样当点击导航的时候就有CSS样式显示了


以上就是快速入门内容,现在可以学习 react-router-dom 其他的内容。

Switch

考虑以下情况:假设注册路由时,有两个一样路径会发生什么现象?

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

运行一下,如图所示
在这里插入图片描述
可以看到,当点击About链接时,Home和About组件都显示了出来,这是不符合实际要求的,这时就要用到了Switch组件。Route默认是全部扫描的,就算路由路径是第一个而且已经成功匹配,还是要向下继续扫描,使用Switch包裹Route,使得一旦路径匹配就不继续向下匹配了,也就是说,一个路径只匹配一次

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

这样下面那个 /about 路径就不会显示了。

Redirect

重定向,当路由没有匹配的时候,给一个指定的路径去匹配,to属性指定一个路径

<Switch>
	<Route exact path="/" component={Home}/>
	<Route path="/about" component={About}/>
	<Route path="/topics" component={Topics}/>
	<Redirect to="/somewhere/else" />
</Switch>

给路由组件传参

前置知识:

路由组件与一般组件
    1.写法不同:
        一般组件:<Demo/>
        路由组件:<Route path="/demo" component={Demo}/>
    2.存放位置不同:
        一般组件:components
        路由组件:pages
    3.接收到的props不同:
        一般组件:写组件标签时传递了什么,就能收到什么
        路由组件:接收到三个固定的属性
                    history:
                                go: ƒ go(n)
                                goBack: ƒ goBack()
                                goForward: ƒ goForward()
                                push: ƒ push(path, state)
                                replace: ƒ replace(path, state)
                    location:
                                pathname: "/about"
                                search: ""
                                state: undefined
                    match:
                                params: {}
                                path: "/about"
                                url: "/about"

假设要给About组件传递一个id参数
方法1:通过传递params参数,浏览器地址栏变为 /about/01

## 传参
const id = '01';
const App = () => (
  <Router>
    <div>
      <ul>
        <li><Link to={`/about/${id}`}>About</Link></li>
      </ul>
      <hr/>
      <Route path="/about/:id" component={About}/>
    </div>
  </Router>
)

## About组件中接收参数 
const { id } = this.props.match.params;
## 在传递时,react默认将参数整理成一个对象
{ id:'01',... }

如有多个参数,只需要继续在Link的to属性后加/接着拼写就行,Route那里同理。

方法2:通过传递search参数,这将显示在地址栏上的urlencoded字符串,需要借助 react 内置的库querystring解析该参数为JSON对象

## 传参
const id = '01';
const App = () => (
  <Router>
    <div>
      <ul>
        <li><Link to={`/about/?id=${id}`}>About</Link></li>
      </ul>
      <hr/>
      ## search传递参数不需要改动 Route
      <Route path="/about" component={About}/>
    </div>
  </Router>
)

## About组件中接收参数 
import qs from 'querystring'
...
const {search} = this.props.location
const { id } = qs.parse(search.slice(1)) ## 截去第一个问号 ?

## 拓展 querystring 另外一个方法 stringify() 可以将JSON对象转换为如下形式
qs.stringify({id:'01',title:'zlfan'}) ---> "id=01&title=zlfan"

方法3:通过传递state参数,该方法在地址栏不会有任何显示,但是刷新浏览器仍然保留住参数state

## 传参
const id = '01';
const App = () => (
  <Router>
    <div>
      <ul>
        <li><Link to={{pathname:'/about',state:{id:'01'}}}>About</Link></li>
      </ul>
      <hr/>
      ## state传递参数不需要改动 Route
      <Route path="/about" component={About}/>
    </div>
  </Router>
)

## About组件中接收参数 
const { id } = this.props.location.state;

withRouter

可以通过 withRouter 高阶组件访问 history 对象的属性和最近的 的 match 。 当路由渲染时, withRouter 会将已经更新的 match , location 和 history 属性传递给被包裹的组件。
将一般组件变成路由组件,即组件props能接收到historylocationmatch三个参数

import React from 'react'
import { withRouter } from 'react-router'
class ShowTheLocation extends React.Component {
	....
}

export default withRouter(ShowTheLocation)

参考:

https://www.bilibili.com/video/BV1wy4y1D7JT?p=77
https://react-router.docschina.org
https://www.jianshu.com/p/6583b7258e78



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值