React Router中的history的一些探究和解释
history
history 是 Facebook 的JavaScript库,用于管理会话历史,
React Router是基于history实现的。
history 包含了 window.history ( HTML5 History API )
history 有以下方法:
- block
在地址栏改变之前,告知地址栏改变即将发生 - createHref
返回当前路径名 - listener
监听地址栏改变,用于地址改变前截取
以下方法用于跳转:
- goBack
返回上一条历史记录 - goForward
返回下一条历史记录 - push (重要)
添加新的历史记录 - replace(重要)
替换当前历史记录 - go
跳转到某条历史记录
两个重要属性
- length
历史记录长度 - location
当前位置的记录
location (history.location)
首先:props.history.location === props.location
location的属性:
- hash
- search
搜索字符串 - pathname
路径名称,常用 - state
可以为location传递一些信息,但不展示在URL上。
比如:
({location}) => <Redirect to={{pathname: "/login", state: {from: location}}}/>
上述代码在Redirect中的to属性是一个对象,state属性将被放到location中,在跳转后可以通过location.state取得
介绍一下应用场景:
首先是ReactRouter官方文档给出的登录认证Demo,在掌握上述内容后,可以试着实现一下,会很有帮助:
https://reacttraining.com/react-router/web/example/auth-workflow
接下来是在我自己的项目中遇到的情况
管理员页面A必须登陆以后才能访问,登录页面记为L
(1)
场景 | history方法 | 当前历史记录 |
---|---|---|
试图访问管理员页面A | ~ | ~ |
验证不通过,重定向至 L | REPLACE | L |
登陆成功,跳转回页面A | REPLACE | A |
你会发现跳转到A后,后退将不会返回到登录页面。 |
(2)
场景 | history方法 | 当前历史记录 |
---|---|---|
管理员停留在页面B 超时 | ~ | ...B |
管理员试图跳转到页面C | ~ | ...B |
验证不通过,重定向至登录页面L | REPLACE | ...L |
登陆成功,跳转回页面B | REPLACE | ...B |
所以登录成功后的跳转需要依靠location传递一个from信息,以便让页面跳转到“登录前”的页面。
(1)中有个需要注意的地方,如果是第一次访问页面A,此时state值为undefined,此时跳转到的页面就不正常,因此必须兜底处理:
const {from} = location.state || {from: {pathname: '/'}};
history.replace(from.pathname);
在管理员页面的Route中,我参考官网的做法,是这样写的:
function AuthRoute({children, ...rest}) {
const isLogin = // 判断登录状态
return (
<Route
{...rest}
render={({location}) => isLogin ? children : <Redirect to={{pathname: "/login", state: {from: location}}}/>}
/>
)
}
match
match 对象具有以下属性:
官方Doc解释:
- params - (object) Key/value pairs parsed from the URL corresponding to the dynamic segments of the path
以键值对的形式,返回路由传递的参数 - isExact - (boolean) true if the entire URL was matched (no trailing characters)
是否精确匹配(exact) - path - (string) The path pattern used to match. Useful for building nested
s
见下例,便于创建嵌套的 Routes - url - (string) The matched portion of the URL. Useful for building nested s
便于创建嵌套的 Links
假设根目录下有用户页面,根据每个用户的id来安排路由:
/users/:id
在该页面下,又可以点击链接访问到用户的“关于”信息,
Link 设置:
<Link to=`${match.url}/about` />
假设此时位于 /users/5,则 match.url 返回 /users/5
Route 设置:
<Route path=`${match.path/about}` component={About} />
假设此时位于 /users/5,则 match.url 返回 /users/:id 而不是具体的id。
暂时记录到这里,有错误或不足请指正