快速入门
下载安装
## 安装 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中,引入了BrowserRouter
,Route
,Link
三个组件,下面开始分别介绍。
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
包裹Link
和Route
的组件,使得UI组件与地址URL保持同步,若Link
和Route
不被BrowserRouter
包裹,则会报错。另外,Link
编写的好的路径,在注册时,Link
和Route
必须要在同一个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能接收到history
,location
,match
三个参数
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