路由用来分发请求,前端是显示页面的,所以它的路由是在找component
,后端是提供服务的,它的路由是在找controller
。
【5种路由方式】
- BrowserRouter:浏览器的路由方式,在开发中最常使用。
- HashRouter:在路径前加入#号成为一个哈希值。Hash模式的好处- 是,再也不会因为我们刷新而找不到我们的对应路径了。
- MemoryRouter:不存储history,所有路由过程保存在内存里,不能进行前进后退,因为地址栏没有发生任何变化。
- NativeRouter:经常配合ReactNative使用,多用于移动端。
- StaticRouter:设置静态路由,需要和后台服务器配合设置,比如设置服务端渲染时使用。
【BrowserRouter】
import { BrowserRouter } from 'react-router-dom'
<BrowserRouter
basename={optionalString}
forceRefresh={optionalBool}
getUserConfirmation={optionalFunc}
keyLength={optionalNumber}
>
<App/>
</BrowserRouter>
1、basename
: 当前位置的基准 URL。如果页面部署在服务器的二级(子)目录,需要将basename
设置到此子目录。 正确的 URL 格式是前面有一个前导斜杠,但不能有尾部斜杠。
<BrowserRouter basename="/calendar"/>
2、getUserConfirmation
:当导航需要确认时执行的函数。默认使用 window.confirm
。
// 使用默认的确认函数
const getConfirmation = (message, callback) => {
const allowTransition = window.confirm(message)
callback(allowTransition)
}
<BrowserRouter getUserConfirmation = {getConfirmation} />
3、forceRefresh
:当设置为 true 时,在导航的过程中整个页面将会刷新。 只有当浏览器不支持 HTML5 的 history API 时,才设置为 true。
const supportsHistory = 'pushState' in window.history
<BrowserRouter forceRefresh={!supportsHistory}/>
4、keyLength
:location.key
的长度。默认是 6。
<BrowserRouter keyLength={12}/>
5、BrowserRouter
只能渲染单一子元素。
【Route】
Route是react-router中最重要的组件,用来匹配请求并渲染相应组件。
1、path
路径的匹配值,可以包括以下几种特殊符号
:paramName – 匹配一段位于 /、? 或 # 之后的 URL。 命中的部分将被作为一个参数。
() – 在它内部的内容被认为是可选的
* – 匹配任意字符(非贪婪的)直到命中下一个字符或者整个 URL 的末尾,并创建一个 splat 参数
例子如下所示:
<Route path="/hello/:name"> // 匹配 /hello/michael 和 /hello/ryan
<Route path="/hello(/:name)"> // 匹配 /hello, /hello/michael 和 /hello/ryan
<Route path="/files/*.*"> // 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg
[注意]Route组件不能像普通组件一样,以属性的形式传递参数,但可以通过path属性来传递,但一定要区分router后面的:_id或:id。
'/category/:_id'
2、component
要显示的组件
import { BrowserRouter as Router, Route } from 'react-router-dom'
<Router>
<div>
<Route exact path="/" component={Home}/>
<Route path="/news" component={NewsFeed}/>
</div>
</Router>
3、render
函数中return
的值就是要显示的内容
<Route path="/home" render={() => <div>Home</div>}/>
4、children
与render
的区别在于,不管有没有匹配,都想显示的内容
const ListItemLink = ({ to, ...rest }) => (
<Route path={to} children={({ match }) => (
<li className={match ? 'active' : ''}>
<Link to={to} {...rest}/>
</li>
)}/>
)
[注意]component/render/children只能三个选一个使用
【匹配规则】
默认地,路由进行宽松匹配。在下面例子中,路由匹配到/one时,既显示组件A,也显示组件B。
<Route path="/one" component={A}/>
<Route path="/one/two" component={B}/>
如果要进行确切匹配
,则需要添加exact
属性。这样,路由匹配到/one时,只显示组件A。
<Route exact path="/one" component={A}/>
<Route path="/one/two" component={B}/>
还有一种是严格匹配
,即斜杠也必须严格匹配。下面例子中,路由匹配到/one/时,会显示组件A,但匹配到/one时,什么都不会显示
<Route strict path="/one/" component={A}/>
[注意]严格匹配并不是确切匹配。下面例子中,路由匹配到/one时,即显示组件A,也显示组件B
<Route strict path="/one" component={A}/>
<Route path="/one/two" component={B}/>
如果要确切匹配,则需要
<Route exact strict path="/one" component={A}/>
但是,一般地,strict属性
很少使用
【属性】
Route默认携带三个props:包括match
、location
、history
如果使用component
,则使用this.props
来获取,如果是render
,则在回调函数中使用参数(props)=>{}
来获取
1、match
match包括以下属性:
params 键值对
isExact 是否确切匹配
path 路径中设置的值
url URL中的path值
2、location
location中包含如下属性:
[注意]直接访问location
,而不是访问history.location
{
key: 'ac3df4', // not with HashHistory!
pathname: '/somewhere'
search: '?some=search-string',
hash: '#howdy',
state: {
[userDefined]: true
}
}
通过Link传递的state,可以在location中获取到
[注意]刚开始时,或者直接刷新浏览器,state是没有值的,只有跳转到该链接时,state才有值。再后来,刷新也有值了。
3、history
history包含如下属性:
length: history栈的长度
action: 当前的action
location: 当前的location对象
history包含如下方法:
push()
goBack() = go(-1)
goForward() = go(1)
go() 跳转到 history栈中的哪个enter
replace(path, [state]) 替换history栈中的当前entry
push(path, [state]) 添加当前entry到history栈中
【Redirect】
Redirect将页面导航到新位置,新位置将覆盖history栈中的当前位置,类似于服务器端的重定向(HTTP 3xx)。
to属性可以是一个字符串,表示跳转的地址。
<Route exact path="/" render={() => (
loggedIn ? (
<Redirect to="/dashboard"/>
) : (
<PublicHomePage/>
)
)}/>
to属性也可以是一个对象
<Redirect to={{
pathname: '/login',
search: '?utm=your+face',
state: { referrer: currentLocation }
}}/>
push属性为true
时,表示添加新记录到history栈
中,而不是替换当前记录。
<Redirect push to="/somewhere/else"/>
【Link】
Link是对a标签的封装,提供无刷新的页面跳转。Link标签主要的属性是to属性。
1、一般地,to是一个字符串
<Link to="/about">关于</Link>
2、也可以写成对象的形式
<Link to={{
pathname: '/courses',
search: '?sort=name',
hash: '#the-hash',
state: { fromDashboard: true }
}}/>
[注意]在Link里的子组件或同组件的点击事件,最好加上阻止默认行为和阻止冒泡。
<Link>
<div onclick={}></div>
</Link>
<Link onclick={}>
【NavLink】
NavLink相对于Link来说,增加了一些样式属性
activeClassName
表示被匹配的a标签的样式名;activeStyle
表示被匹配的a标签的样式。
<NavLink
to="/faq"
activeClassName="selected"
>FAQs</NavLink>
<NavLink
to="/faq"
activeStyle={{
fontWeight: 'bold',
color: 'red'
}}
>FAQs</NavLink>
[注意]link
和history.push
都不支持指向外网地址,如果要跳转到外网,则需要使用window对象下的location对象
。
【Switch】
渲染Route或Redirect匹配到的第一个子元素
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
</Switch>
[注意]switch必须直接包括Route,中间不可包含div,否则不生效
跳转。
如果在实现逻辑跳转,可使用如下代码实现:
// utils/history.js
import createBrowserHistory from 'history/createBrowserHistory'
const customHistory = createBrowserHistory()
export default customHistory
引用如下:
import history from '@/utils/history'
// 跳转到首页
history.push('/')
要特别注意的是,如果使用utils/history.js
,需要使用Router history={history}
,而不是BrowserRouter
因为全局只能有一个history实例。 使用import { BrowserRouter as Router }
语句,会自动创建一个history实例
的,相当于有两个实例,则会出现URL发生变化,刷新页面后,页面才跳转的情况。
import { Router, Route, Switch, Redirect } from 'react-router-dom'
import history from '@/utils/history'
<Router history={history}>
<Switch>
<Route path="/login" component={Login} />
<Route path="/" render={props => {if (sessionStorage.getItem('token') && sessionStorage.getItem('user')) {return <Home {...props} />
}
return <Redirect to="/login" />
}} />
</Switch>
</Router>
【传参】
history.push
方法也可以携带参数,方法如下
history.push({
pathname: '/about',
search: '?the=search',
state: { some: 'state' }
})