React学习:路由定义及传参、数据复用-学习笔记
在React中使用react-router-dom路由
使用React构建的单页面应用,要想实现页面间的跳转,首先想到的就是使用路由。在React中,常用的有两个包可以实现这个需求,react-router
和react-router-dom
。
安装
首先进入项目目录,使用npm安装react-router-dom:
cnpm install react-router-dom --save
涉及知识点:
一般一个路由的至少会有三大组件,分别是BrowserRouter
、Route
、Link
;
BrowserRouter
:可以将其理解为一个容器,用来放Route、Link。
Route
:可以理解为当前要展示的视图,会根据路由中不同的路径呈现不同展示。Route会有三大props,分别是location、history、match
;其中match有包含params、isExact、path、url这些属性。
Link
:申明了路由的路由,要跳转的地方,简单的可以理解为“要到哪去”。
常用API
路由容器组件
BrowserRouter
: 浏览器自带的API,restful风格(需要后台做相应的调整);
HashRouter
: 使用hash方式进行路由;
MemoryRouter
: 在内存中管理history,地址栏不会变化。在reactNative中使用。
Route标签
该标签有三种渲染方式component
、render
、children
(绝大多数情况使用component组件就好了);
三种渲染方式都会得到三个属性match、history、location
;
渲染组件时,route props
跟着一起渲染;
children方式渲染会不管地址栏是否匹配都渲染一些内容,在这里加动画一时很常见的做法。
Link标签
to
: 后面可以接字符串,也可以跟对象(对象可以是动态地添加搜索的信息);
replace
: 当设置为true时,点击链接后将使用新地址替换掉访问历史记录里面的原地址。
NavLink标签
<NavLink>
是<Link>
的一个特定版本, 会在匹配上当前URL的时候会给已经渲染的元素添加样式参数;
activeClassName
,当地址匹配时添加相应class;
activeStyle
,当地址匹配时添加相应style;
exact
,当地址完全匹配时,才生效;
isActive
,添加额外逻辑判断是否生效。
Prompt标签
when
: when的属性值为true时启用防止转换;
message
: 后面可以跟简单的提示语,也可以跟函数,函数是有默认参数的。
Redirect标签
<Redirect/>
可以写在<Route/>
的render
属性里面,也可以跟<Route/>
平级;
to
: 依旧是可以跟字符串或对象;
push
: 添加该属性时,地址不会被覆盖,而是添加一条新纪录;
from
: 重定向,与<Route/>
平级时。
match
params
: 通过解析URL中动态的部分获得的键值对;
isExact
: 当为true时,整个URL都需要匹配;
path
: 在需要嵌套<Route/>
的时候用到;
url
: 在需要嵌套<Link/>
的时候会用到;
获取方式:
this.props.match
导入方式:
import {
BrowserRouter as Router,
Route, // 这是基本的路由块
Link, // 这是a标签
Switch // 这是监听空路由的
Redirect // 这是重定向
Prompt // 防止转换
} from 'react-router-dom'
react-router和react-router-dom的区别是什么呢?
为什么有时候我们看到如下的写法:
写法1:
import {Swtich, Route, Router, HashHistory, Link} from 'react-router-dom';
写法2:
import {Switch, Route, Router} from 'react-router';
import {HashHistory, Link} from 'react-router-dom';
react-router
: 实现了路由的核心功能
react-router-dom
: 基于react-router,加入了在浏览器运行环境下的一些功能,例如:Link组件,会渲染一个a标签,Link组件源码a标签行; BrowserRouter和HashRouter组件
其他函数
replace
有些场景下,重复使用push或a标签跳转会产生死循环,为了避免这种情况出现,react-router-dom提供了replace。在可能会出现死循环的地方使用replace来跳转:
this.props.history.replace('/detail');
goBack
场景中需要返回上级页面的时候使用:
this.props.history.goBack();
简单例子
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import Routes from './project/routes'
import * as serviceWorker from './serviceWorker'; //资源缓存
//React.StrictMode严格模式
ReactDOM.render(
<React.StrictMode>
<Routes />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
import React,{Component} from 'react';
import {BrowserRouter as Router, Route} from 'react-router-dom'
//导入组件
import Home from './home/index'
import Login from './login/index'
class Routes extends Component {
render(){
return (
<Router>
<div>
<Route path='/login' component={Login} ></Route>
<Route path='/index' component={Home} ></Route>
</div>
</Router>
)
}
}
export default Routes;
路由定义及传参
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import 'antd/dist/antd.css'
import Routes from './project/routes/routes'
import * as serviceWorker from './serviceWorker'; //资源缓存
//React.StrictMode严格模式
ReactDOM.render(
<React.StrictMode>
<Routes />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
路由传参:
import React,{Component} from 'react';
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
//导入组件
import Banner from '../other/banner'
// 音乐组件
class Music extends Component {
render(){
return <h1>Music {this.props.location.query}</h1>
}
}
//类别组件
class Category extends Component {
render(){
return <h1>Category {this.props.match.params.id}</h1>
}
}
class Routes extends Component {
constructor(){
super();
this.state = {
n:999
}
}
render(){
return (
<Router>
{/* 跳转 */}
<ul>
<li>
<Link to='/index/1/10'>首页</Link>
</li>
<li>
<Link to={'/tool/'+this.state.n}>工具模块</Link>
</li>
<li>
<Link to={{pathname:'/music',query:'123456'}}>音乐模块</Link>
</li>
</ul>
{/* 渲染出口 */}
<div>
<Route path='/tool/:id' component={Category} ></Route>
<Route path='/index/:id/:size' component={Banner} ></Route>
<Route path='/music' component={Music} ></Route>
</div>
</Router>
)
}
}
export default Routes;
若将routes写到另一个文件中,动态加载:
import React,{Component} from 'react';
//导入组件
import Banner from '../other/banner'
// 音乐组件
class Music extends Component {
render(){
return <h1>Music</h1>
}
}
//类别组件
class Category extends Component {
render(){
return <h1>Category </h1>
}
}
let routes = [
{
path:'/index',
component:Banner
},
{
path:'/tool',
component:Category
},
{
path:'/music',
component:Music
}
]
export default routes;
import React,{Component} from 'react';
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
import routes from './index'
class Routes extends Component {
constructor(){
super();
this.state = {
n:999
}
}
render(){
return (
<Router>
{/* 跳转 */}
<ul>
<li>
<Link to='/index'>首页</Link>
</li>
<li>
<Link to='/tool'>工具模块</Link>
</li>
<li>
<Link to='/music'>音乐模块</Link>
</li>
</ul>
{/* 渲染出口 */}
<div>
{
routes.map((item,i)=>{
return <Route key={i} path={item.path} component={item.component} ></Route>
})
}
</div>
</Router>
)
}
}
export default Routes;