LANTEN

react-router-dom @4.x 重定向

2017-12-04

配置 404

可以使用 Switch 组件包裹 Route

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React from 'react'
import {
BrowserRouter as Router,
Route, Switch,
} from 'react-router-dom'

class Root extends React.Component {
render() {
return (
<Router>
<Switch>
<Route path={'/login'} component={Login} exact />
<Route component={NoMatch} type="404" />
</Switch>
</Router>
)
}
}

设置一个不包含 keyRoute , 当用户访问路由中不存在的路径时,跳转到此处,其中type="404" 是组件 NoMatch 中所接收的参数

配置未登录重定向

组件 Redirect 将导航到一个新位置。新的位置将在历史堆栈覆盖当前位置

使用 Redirect 可以轻松实现未登录重定向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import {
BrowserRouter as Router,
Route, Switch, Redirect,
} from 'react-router-dom'

class Root extends React.Component {
render() {
return (
<Router>
<Switch>
<Route path={cfg.appname + '/login'} component={Login} exact />
{pageRouter.map((val, i) => <PageRoute key={i} {...val} />)}
<PageRoute component={NoMatch} type="404" />
</Switch>
</Router>
)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const PageRoute = ({ component: Component, ...rest }) => {
// 路由配置中的 params 可以配置默认参数
return (
<Route {...rest} render={props => {

if (global.isLogin) {
return (
<App params={rest.params || {}}>{<Component {...props} params={rest.params || {}} />}</App>
)
} else {
return (
<Redirect to={{
pathname: cfg.appname + '/login',
state: { from: { ...props.location, ...rest.params } }
}} />
)
}

}} />
)
}

组件 APP 是所有页面的公共包裹层,如果不需要可以直接渲染 Component

配合 403 权限拦截

完整例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React from 'react'
import ReactDOM from 'react-dom'
import {
BrowserRouter as Router,
Route, Switch, Redirect,
} from 'react-router-dom'

class Root extends React.Component {
render() {
return (
<Router>
<Switch>
<Route path={cfg.appname + '/login'} component={Login} exact />
{privateRoute.map((val, i) => <PrivateRoute key={i} {...val} />)}
{pageRouter.map((val, i) => <PageRoute key={i} {...val} />)}
<PageRoute component={NoMatch} type="404" />
</Switch>
</Router>
)
}
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// 未登录拦截的路由
const PageRoute = ({ component: Component, ...rest }) => {
// 路由配置中的 params 可以配置默认参数
return (
<Route {...rest} render={props => {
if (global.isLogin) {
return (
<App params={rest.params || {}}>{<Component {...props} params={rest.params || {}} />}</App>
)
} else {
return (
<Redirect to={{
pathname: cfg.appname + '/login',
state: { from: { ...props.location, ...rest.params } }
}} />
)
}
}} />
)
}

// 权限拦截的路由
const PrivateRoute = ({ component: Component, ...rest }) => {
return (
<Route {...rest} render={props => {

if (global.isLogin) {
let key = props.history.location.pathname.split('/')
key = key[key.length - 1]

let com = !key || hasMenu(key) ? (
<Component {...props} params={rest.params || {}} />
):(
<NoMatch {...props} type="403" text="你没有访问权限" />
)

return (
<App params={rest.params || {}}>{com}</App>
)
} else {
return (
<Redirect to={{
pathname: cfg.appname + '/login',
state: { from: { ...props.location, ...rest.params } }
}} />
)
}

}} />
)
}

const hasMenuNode = ({ childrenMenuTreeNodeList, menuCode }, key) => {
let flg = false
if (childrenMenuTreeNodeList) {
for (let i = 0; i < childrenMenuTreeNodeList.length; i++) {
const val = childrenMenuTreeNodeList[i];
flg = hasMenuNode(val, key)
if (flg) return flg
}
} else {
if (menuCode === key) {
flg = true
return flg
} else {
flg = false
}
}
return flg
}

// 判断权限
const hasMenu = (key) => {
for (let i = 0; i < global.menuData.length; i++) {
const val = global.menuData[i];
let flg = hasMenuNode(val, key);
if (flg) return flg
}
return false
}

路由配置

1
2
3
4
5
6
7
8
9
10
// 公共路由
const pageRouter = [
{ path: '/', component: Home, exact, params: { name: 'home' } }
...
]
// 受保护的路由
const privateRoute = [
{ path: '/page2', component: Demo, exact, params: { name: 'demo2' } }
...
]

判断 路由中的 key 是否包含在 global.menuData 中,如果没有则跳转到403

扫描二维码,分享此文章