npm包的区别
首先从react-router的npm包开始看起,分别有react-router和react-router-dom,两者的区别在于后者具有一些dom api,比如Link、BrowserRouter、HashRouter。不难发现react-router-dom具有一些在浏览器上所需要的api,而react-router只有核心api,所以我们总结下
- react-router 路由核心功能包
- react-router-dom 在浏览器上使用的react路由
- react-router-native 在app上使用的react路由
其中react-router-dom和react-router-native都继承自react-router,所以我们在浏览器上开发只需要引入react-router-dom即可
react-router-dom api详解
我最先接触的框架是vue,vue中的路由配置使用的是配置文件,而react使用的是jsx来配置路由,所以初次学习会有点别扭。
HashRouter和BrowserRouter
其实就是路由的hash和history两种模式(要是不了解这两种模式之间的区别那就需要去恶补下啦)
并且这两个组件是路由的容器,必须在最外层
// hash模式
ReactDom.render(
<HashRouter>
<Route path="/" component={Home}/>
</HashRouter>
)
// history模式
ReactDom.render(
<BrowserRouter>
<Route path="/" component={Home}/>
</BrowserRouter>
)
复制代码
下面说说HashRouter和BrowserRouter上的参数
- basename 路由的基础链接,用来部署到非根目录下,比如你需要将项目部署到 www.xxxx.com/web 下,则设置basename="/web"
- getUserConfirmation 用来拦截Prompt组件,并且决定是否跳转
- forceRefresh 用来设置是否强制浏览器整体刷新,默认值为false
- keLength 用来设置location.key的长度,默认是6,可以自定义
Prompt
Prompt是用来提示用户是否要跳转,给用户提示信息默认使用window.confirm,可以结合getUserConfirmation构建自定义提示信息
<Prompt message={location => {
return '请确认'
}}/>
如果直接返回true,则不会弹窗
复制代码
Route
Route是路由的一个原材料,它是控制路径对应显示的组件
Route的参数
- path 跳转的路径
- component 对应路径显示的组件
- render 可以自己写render函数返回具体的dom,而不需要去设置component
- location 传递route对象,和当前的route对象对比,如果匹配则跳转
- exact 匹配规则,true的时候则精确匹配。
path | url | 是否开启 | 匹配结果 |
---|---|---|---|
/a | /a/b | false | yes |
/a | /a/b | true | no |
- sensitive 是否区分path的大小写
path | url | 是否开启 | 匹配结果 |
---|---|---|---|
/a | /a | true | yes |
/a | /A | true | yes |
- strict 是否匹配后面的/
path | url | 是否开启 | 匹配结果 |
---|---|---|---|
/a | /a/ | true | yes |
/a | /a/c | true | yes |
/a | /a | true | no |
Router
低级路由,适用于任何路由组件,主要和redux深度集成,使用必须配合history对象
使用Router路由的目的是和状态管理库如redux中的history同步对接
<Router history={history}>
...
</Router>
复制代码
Link和NavLink
两者都是跳转路由,NavLink的参数更多些
Link的api
- to 有两种写法,表示跳转到哪个路由
- 字符串写法
<Link to="/a"/> 复制代码
- 对象写法
<Link to={{ pathname: '/courses', search: '?sort=name', hash: '#the-hash', state: { fromDashboard: true } }}/> 复制代码
- 字符串写法
- replace 就是将push改成replace
- innerRef 访问Link标签的dom
NavLink的api
- Link的所有api
- activeClassName 路由激活的时候设置的类名
- activeStyle 路由激活设置的样式
- exact 参考Route,符合这个条件才会激活active类
- strict 参考Route,符合这个条件才会激活active类
- isActive 接收一个回调函数,active状态变化的时候回触发,返回false则中断跳转
const oddEvent = (match, location) => {
console.log(match,location)
if (!match) {
return false
}
console.log(match.id)
return true
}
<NavLink isActive={oddEvent} to="/a/123">组件一</NavLink>
复制代码
- location 接收一个location对象,当url满足这个对象的条件才会跳转
<NavLink to="/a/123" location={{ key:"mb5wu3", pathname:"/a/123" }}/>
复制代码
Redirect
Redirect重定向很简单,我们直接看代码即可
// 基本的重定向
<Redirect to="/somewhere/else" />
// 对象形式
<Redirect
to={{
pathname: "/login",
search: "?utm=your+face",
state: { referrer: currentLocation }
}}
/>
// 采用push生成新的记录
<Redirect push to="/somewhere/else" />
// 配合Switch组件使用,form表示重定向之前的路径,如果匹配则重定向,不匹配则不重定向
<Switch>
<Redirect from='/old-path' to='/new-path'/>
<Route path='/new-path' component={Place}/>
</Switch>
复制代码
Switch
路由切换,只会匹配第一个路由,可以想象成tab栏
Switch内部只能包含Route、Redirect、Router
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
</Switch>
复制代码
withRouter
当一个非路由组件也想访问到当前路由的match,location,history对象,那么withRouter将是一个非常好的选择,可以理解为将一个组件包裹成路由组件
import { withRouter } from 'react-router-dom'
const MyComponent = (props) => {
const { match, location, history } = this.props
return (
<div>{props.location.pathname}</div>
)
}
const FirstTest = withRouter(MyComponent);
复制代码
history对象
用过vue的都知道,vue-router有组件形式的导航,也有编程式导航,那react-router怎么使用api来控制前进后退和刷新呢?这就需要我们来说明下history对象的作用了
其实在每个路由组件中我们可以使用this.props.history获取到history对象,也可以使用withRouter包裹组件获取,
在history中封装了push,replace,go等方法,具体内容如下
History {
length: number;
action: Action;
location: Location;
push(path: Path, state?: LocationState): void; // 调用push前进到一个地址,可以接受一个state对象,就是自定义的路由数据
push(location: LocationDescriptorObject): void; // 接受一个location的描述对象
replace(path: Path, state?: LocationState): void; // 用页面替换当前的路径,不可再goBack
replace(location: LocationDescriptorObject): void; // 同上
go(n: number): void; // 往前走多少也页面
goBack(): void; // 返回一个页面
goForward(): void; // 前进一个页面
block(prompt?: boolean | string | TransitionPromptHook): UnregisterCallback;
listen(listener: LocationListener): UnregisterCallback;
createHref(location: LocationDescriptorObject): Href;
}
复制代码
这样我们想使用api来操作前进后退就可以调用history中的方法啦