loading

React Router

路由,在日常的前端开发中感觉是一个必不可少的,从实习做项目开始,无论是后台管理页面还是前台的门户网页,总是在和它打交道。所以在前面几天跟着官网陆陆续续敲了几天react的基础上,为了后面能够完成一个简单的后台管理项目,对照公司里vue项目经验,今天继续学习react router文档地址 (opens new window)

# 官网示例

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  useRouteMatch,
  useParams
} from "react-router-dom";

export default function App() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/topics">Topics</Link>
          </li>
        </ul>

        <Switch>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/topics">
            <Topics />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {
  return <h2>Home</h2>;
}

function About() {
  return <h2>About</h2>;
}

function Topics() {
  let match = useRouteMatch();

  return (
    <div>
      <h2>Topics</h2>

      <ul>
        <li>
          <Link to={`${match.url}/components`}>Components</Link>
        </li>
        <li>
          <Link to={`${match.url}/props-v-state`}>
            Props v. State
          </Link>
        </li>
      </ul>

      {/* The Topics page has its own <Switch> with more routes
          that build on the /topics URL path. You can think of the
          2nd <Route> here as an "index" page for all topics, or
          the page that is shown when no topic is selected */}
      <Switch>
        <Route path={`${match.path}/:topicId`}>
          <Topic />
        </Route>
        <Route path={match.path}>
          <h3>Please select a topic.</h3>
        </Route>
      </Switch>
    </div>
  );
}

function Topic() {
  let { topicId } = useParams();
  return <h3>Requested topic ID: {topicId}</h3>;
}
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
81
82
83
84
85
86
87
88

实现效果:

可以看出官网示例实现了一个嵌套路由效果,但是代码中从react-router-dom中导入的SwitchRouteLinkuseRouteMatchuseParams这些api,看上去我似乎知道它干了什么,但我还是继续查看文档,学习学习这些常用的API

# 组件分类

react router的组件主要分为三类:

  • 路由器,例如<BrowserRouter><HashRouter>
  • 路由匹配器,例如<Route><Switch>
  • 导航(路线更改器),例如<Link><NavLink><Redirect>

# 路由器

react-router-dom提供<BrowserRouter><HashRouter>路由器,两者的区别主要在于它们存储url和web服务器通信的方式。

# BrowserRouter

使用常规的url路径,例如http://baidu.com/path,它的原理是通过JavaScript的history属性实现的。

# HashRouter

使用hash路径,例如http://baidu.com/#/path,它的原理是通过监听url中的hash的变化实现的。

# 路由匹配器

# Router

通过匹配组件定义的path,当path匹配成功时会渲染该组件。

<Route path="/home">
	<Home />
</Route>
1
2
3

当url中的路径匹配上了home页面即渲染Home组件。

# Switch

<Switch>被渲染时,会搜索它的子<Route>,当找到其中第一个path与当前url匹配时,渲染该对象并忽略其他<Route>。如果没有找到<Route>匹配项,则<Switch>渲染器不会渲染任何内容。

<Switch>  
  <Route path="/about">
    <About />
  </Route>
  <Route path="/topics">
    <Topics />
  </Route>
  <Route path="/">
    <Home />
  </Route>
</Switch>
1
2
3
4
5
6
7
8
9
10
11

使用上面官网的示例代码,当我们在搜索/about的时候,<About><Home>组件都匹配了,但因为Switch的特性页面只渲染了<About>就不会再往下匹配了。因此我们应该将根目录'/'匹配的<Route>放在最后的<Switch>中。

# 导航

<Link>组件最终会渲染为a标签,同时通过to参数切换路径到指定目录。

<NavLink><Link>的一个特定版本,会在匹配上当前url的时候为已经渲染的元素添加参数,参数有:

  • activeClassName(string):设置选中样式,默认值为active。
  • activeStyle(object):当元素被选中时,为此元素添加样式。
  • exact(bool):为true时,只有当导致和完全匹配class和style才会应用。
  • strict(bool):为true时,在确定为位置是否与当前URL匹配时,将考虑位置pathname后的斜线。
  • isActive(func)判断链接是否激活的额外逻辑的功能。

// activeClassName选中时样式为selected
<NavLink
  to="/faq"
  activeClassName="selected"
>FAQs</NavLink>
 
// 选中时样式为activeStyle的样式设置
<NavLink
  to="/faq"
  activeStyle={{
    fontWeight: 'bold',
    color: 'red'
   }}
>FAQs</NavLink>
 
// 当event id为奇数的时候,激活链接
const oddEvent = (match, location) => {
  if (!match) {
    return false
  }
  const eventID = parseInt(match.params.eventID)
  return !isNaN(eventID) && eventID % 2 === 1
}
 
<NavLink
  to="/events/123"
  isActive={oddEvent}
>Event 123</NavLink>
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

# Redirect

强制导航,通过参数to重定向到指定页面。

//重定向到登录页
<Redirect to="/login" />
1
2

# Hook

React Router附带有一些Hook,可让您访问路由器的状态并从组件内部执行导航,必须使用React >= 16.8才能使用这些Hook。

# useHistory

使用该Hook,可以访问浏览器的history对象,一般用于路由调整。

# useLocation

使用该Hook,可以获取location对象,当url改变时,就会返回一个新的对象,一般同useEffect一同使用。

# useParams

使用该Hook,可以获取匹配的url参数,例如路由定义为/home/:value,当访问该路径时,就可以通过该钩子获取值home,修改一下上面官网代码。

function App() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/getParam/123456">Topic</Link>
          </li>
        </ul>

        <Switch>
          <Route path="/getParam/:vuele">
            <ParamVal />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function ParamVal() {
  let { vuele } = useParams();
  return <h3>url传值为: {vuele}</h3>;
}

function Home() {
  return <h3>Home</h3>;
}
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

效果:

# useRouteMatch

useRouteMatch钩子尝试以与<Route>相同的方式匹配当前URL。它主要用于访问匹配数据,而无需实际渲染<Route>

注意点:

  • 不接受任何参数时并返回当前<Route>的match对象
  • 接受单个参数时,该参数与matchPath的props参数相同,可以是字符串的路径名,也可以是带有匹配的Route接受道具的对象。
最近更新时间: 2021/08/13 15:27:23
最近更新
01
2021/10/23 00:00:00
02
2021/08/18 17:00:03
03
2021/07/04 15:26:36