React-路由

React-路由

Vscode插件

Auto Import - ES6, TS, JSX, TSX

安装Route组件

npm i react-router-dom

Route组件介绍

  • BrowserRouter:所有需要路由的组件,都要包裹在BrowserRouter组件内
  • Link:跳转到某个链接,to属性表示跳转到的链接
  • Routes:类似于C++中的switch,匹配第一个路径
  • Route:路由,path属性表示路径,element属性表示路由到的内容

各文件代码设置

由于最终所有的组件的出口放在 index.js 中,路由跳转需要在此进行一些设置

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import App from './components/app';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// React.StrictMode 为严格模式,会自动检测并提出一些错误或警告信息
<React.StrictMode>
{/* BrowserRouter进行组件跳转时可以传递任意参数实现组件间的通信 */}
{/* 所有需要路由的组件,都要包裹在BrowserRouter组件内 */}
<BrowserRouter>
<App></App>
</BrowserRouter>
</React.StrictMode>
);

然后我们需要构建一个导航栏,用于各种 URL 跳转

其中 <Link></Link> 于与 <a></a> 类似,但一个用 to,一个用href

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
import React, {Component} from "react";
import { Link } from 'react-router-dom';

class NavBar extends Component {
state = { }
render() {
return (
<React.Fragment>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<div className="container-fluid">
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav">
<li className="nav-item">
<Link className="nav-link" to="/">Home</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/up1">小鸟游杏子Official</Link>
</li>
</ul>
</div>
</div>
</nav>
</React.Fragment>
);
}
}

export default NavBar;

我们将在app.jsx中,根据路由来选择要展示的界面

navbar.jsx 中,<Link></Link> 中的 to 指向的是一个人为自己命名的 URL

app.jsx 中,我们将使用 <Route></Route> 中的 path 属性 去匹配当前网页的 URL,当我们触发<Link></Link> 时,对应的<Route></Route> 就会根据 element属性去对应到需要展示的组件页面

重定向

同时可以定义一个404 notfound.jsx 界面,即不存在的 URL 会匹配到该界面

1
2
3
<Route path="/404" element={<NotFound></NotFound>}></Route>
{/* 重定向跳转到/404:如果url不是上面的任何一个,则会跳转到/404 */}
<Route path="*" element={<Navigate replace to="/404"></Navigate>}></Route>

app.jsx 大部分代码(后续补充以单独的代码表示)

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
import React, { Component } from 'react';
import NavBar from './content/navbar';
// Route需要引入三个库
import { Routes, Route, Navigate } from 'react-router-dom';

import Home from './home';
import Up1 from './up1';
import NotFound from './notfound';

class App extends Component {
state = { }
render() {
return (
// React.Fragment可以看作一个虚的div块,
// 在里面可以写多个节点的html内容
<React.Fragment>
{/* 导航栏展示 */}
<NavBar></NavBar>

{/* 根据点击导航栏选择不同的路由展示不同的界面 */}
{/* 这里由一个bootstrap样式库中的container来包裹所有可能展示的页面 */}
<div className="container">
{/* 由于几个页面的之间是不包含的互斥关系,所以需要使用Routes包裹 */}
<Routes>
<Route path="/" element={<Home></Home>}></Route>
{/* 每个Route都需要一个path属性,path属性是一个url,
当URL匹配一个Route时,这个Route中定义的组件就会被渲染出来。 */}
<Route path="/up1" element={<Up1></Up1>}></Route>

<Route path="/404" element={<NotFound></NotFound>}></Route>
{/* 重定向跳转到/404:如果url不是上面的任何一个,则会跳转到/404 */}
<Route path="*" element={<Navigate replace to="/404"></Navigate>}></Route>
</Routes>
</div>
</React.Fragment>
);
}
}

export default App;
URL中传递参数

(动态改变路由,来展示不同的内容) (也可以是 组件通过 <Route></Route> 给另一个组件传递参数

新建一个 up1content.jsx,用于展示 up1.jsx 中的不同内容,且 up1content.jsx 的内容是在 app.jsx 中展示的,

小例子:

1
<Route path="/linux/:chapter_id/:section_id/" element={<Linux />} />

所以需要在 app.jsx 中添加

1
2
3
import Up1Content from './content/up1content';

<Route path="/up1/content/:chapter" element={<Up1Content></Up1Content>}></Route>

这里还用到了数组的map方法,用于快速循环构建多个重复的元素,还有一个属性key需要注意

代码中的 one_dynamic.id 就是<Route></Route>path 属性中的 :chapter

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
import React, {Component} from "react";
import { Link } from 'react-router-dom';

class Up1 extends Component {
state = {
dynamics: [
{id:1, title: '动态1'},
{id:2, title: '动态2'},
{id:3, title: '动态3'},
]
}
render() {
return (
<React.Fragment>
<h1>小鸟游杏子Official</h1>
<div>
{this.state.dynamics.map(one_dynamic => (
<div key={one_dynamic.id}>
<Link to={`/up1/content/${one_dynamic.id}`}>
{one_dynamic.id + '. ' + one_dynamic.title}
</Link>
</div>
))}
</div>
</React.Fragment>
);
}
}

export default Up1;
在 app1.jsx 中,<Route></Route>将从up1.jsx 获得的参数:chapter通过element传递给 up1content.jsx

up1content.jsx 类组件中,获取参数(函数组件获取方式更简单,作为补充) (类组件获取会警告,看着不舒服)

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
// import React, { Component } from 'react';
import React from 'react';

import {useParams} from 'react-router-dom';

// class Up1Content extends Component {
// state = { }
// render() {
// return (
// <React.Fragment>
// <h1>从URL传来的参数 - {this.props.params.chapter}</h1>
// </React.Fragment>
// );
// }
// }

// export default (props) => (
// <Up1Content
// {...props}
// params={useParams()}
// />
// )

// URL中传递参数:函数组件写法
const Up1Content = () => {
console.log(useParams());
let params = useParams();
return (
<React.Fragment>
<h1>从URL传来的参数 - {params.chapter}</h1>
</React.Fragment>
);
}

export default Up1Content;

效果展示:


嵌套路由(局部渲染?)

1
2
3
4
5
<Route path="/web" element={<Web />}>
<Route index path="a" element={<h1>a</h1>} />
<Route index path="b" element={<h1>b</h1>} />
<Route index path="c" element={<h1>c</h1>} />
</Route>

注意:需要在父组件中添加<Outlet></Outlet>组件,用来填充子组件的内容。

1
import {Outlet} from 'react-router-dom';

本博客所有文章除特别声明外,转载请注明出处!