React学习-路由
发表于|更新于
|阅读量:
SPA理解
SPA (Single Page Application)
基本使用
在React中,路由通常使用react-router-dom库来实现。以下是一个基本的路由组件使用示例。
1.安装依赖:
1
| npm install react-router-dom
|
2.创建路由组件:在项目中创建一个路由组件,例如App.js
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
| import React from 'react' import {BrowserRouter,Route,Routes,Link} from 'react-router-dom'
const Home = () => <h2>Home</h2>; const About = () => <h2>About</h2>; const Contact = () => <h2>Contact</h2>;
function App(){ return ( <BrowserRouter> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about">About</Link> </li> <li> <Link to="/contact">Contact</Link> </li> </ul> </nav> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/contact" element={<Contact />} /> </Routes> </BrowserRouter> ) }
|
BrowserRouter:用于包裹整个应用,提供路由功能
Route:定义路由路径和对应的组件
Routes:包裹所有的Route组件,用于匹配当前URL并渲染对应的组件
Link用于在应用中导航,不会导致页面刷新
一般组件与路由组件
功能上
一般组件:普通React组件,用于构建应用的UI部分。在不同的页面或视图中复用
路由组件:根据URL路径渲染特定的页面或视图,定义不同 的部分,每个部分对应一个URL。实现单页面应用(SPA)。提供导航和页面切换功能
定义上
一般组件:使用函数组件或者类组件,不依赖于URL,可以传递props来定制组件行为
路由组件:使用函数组件或类组件。通过Route组件定义路径,并在Routes管理。可以使用useParams、useLocation等Hook来获取路由信息
代码组织
一般组件:通常存放在components文件夹中
src/
├── components/
│ ├── Button.js
│ ├── Card.js
│ └── Header.js
└── App.js
路由组件:通常存放在pages文件夹中
src/
├── pages/
│ ├── Home.js
│ ├── About.js
│ ├── Contact.js
│ └── UserProfile.js
├── components/
│ ├── Button.js
│ ├── Card.js
│ └── Header.js
└── App.js
NavLink
1
| <NavLink className="list-group"></NavLink>
|
NavLink与Link不同的是可以根据是否匹配链接的路径来应用不同的样式或行为。常用于高亮当前激活的导航链接
在react-router-dom v5老版本中,如果不指定activeClassName来指定属性,通常使用active属性来决定高亮,现在v6版本直接使用className和style来自定义样式
1 2 3 4 5
| <NavLink to="/" className={({ isActive }) => (isActive ? 'active' : 'inactive')} style={({ isActive }) => ({ fontWeight: isActive ? 'bold' : 'normal', color: isActive ? 'red' : 'blue', })}> Home </NavLink>
|
Routes
在老版本v5中是Switch组件,在新版v6版本中是Routes替代了。它会自动选择与当前URL最匹配的路由,并且支持嵌套路由,并且路径匹配是按顺序进行的。
介绍一下用法:
1.基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import Home from './components/Home'; import About from './components/About'; import Dashboard from './components/Dashboard'; import NotFound from './components/NotFound';
function App() { return ( <Router> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/dashboard" element={<Dashboard />} /> {/* 匹配不到时显示404 */} <Route path="*" element={<NotFound />} /> </Routes> </Router> ); }
export default App;
|
2.使用element属性
Route组件使用element属性来指定要渲染的组件,而不是之前的component属性
1
| <Route path="/about" element={<About />} />
|
3.精确匹配
在老版本v5中,路径匹配有模糊匹配的情况出现,例如下面
1 2 3 4 5 6 7
| <BrowserRouter> <Link to="/home/a">Home</Link> <Switch> <Route path="/home" element={<Home/>}/> </Switch/> </BrowserRouter>
|
在Link组件的to属性多了一个’a’路径后缀,但是在Route组件中path属性没有,但是仍能匹配上,这就是模糊匹配。如果要精确匹配,需要将path改成exact path
但是在v6版本中,默认匹配是精确的,即直接使用path即可,不需要显示设置exact属性
1 2 3 4
| <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes>
|
Navigate
在react-route-dom v5版本中,使用Redirect组件将用户从一个路径重定向到另一个路径
1 2 3 4 5 6 7 8 9
| <Router> <Switch> <Route path="/home" exact component={Home} /> <Route path="/about" component={About} /> <Route path="/old-page" component={OldPage} /> <Redirect from="/old-page" to="/about" /> <Redirect to="/404" /> </Switch> </Router>
|
当访问/old-page会自动重定向到/about中,当访问都匹配不上时,重定向到/404页面中
在react-routr-dom v6版本中,使用Navigate组件实现重定向
1 2 3 4 5 6 7 8
| <Router> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/old-page" element={<Navigate to="/about" replace />} /> <Route path="*" element={<Navigate to="/" replace />} /> </Routes> </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
| import React from 'react'; import { BrowserRouter as Router, Route, Routes, Link, Navigate } from 'react-router-dom';
const Dashboard = () => ( <div> <h2>Dashboard</h2> <nav> <ul> <li><Link to="profile">Profile</Link></li> <li><Link to="settings">Settings</Link></li> </ul> </nav> <Routes> <Route index element={<DashboardHome />} /> <Route path="profile" element={<Profile />} /> <Route path="settings" element={<Settings />} /> <Route path="*" element={<Navigate to="profile" replace />} /> </Routes> </div> );
const DashboardHome = () => <h3>Welcome to your Dashboard</h3>; const Profile = () => <h3>Profile Page</h3>; const Settings = () => <h3>Settings Page</h3>;
function App() { return ( <Router> <nav> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/dashboard">Dashboard</Link></li> </ul> </nav> <Routes> <Route path="/" element={<Home />} /> <Route path="/dashboard/*" element={<Dashboard />} /> <Route path="*" element={<Navigate to="/" replace />} /> </Routes> </Router> ); }
const Home = () => <h2>Home</h2>;
export default App;
|
向路由组件传递参数
1.params参数
路由链接需要携带参数
1
| <Link to='demo/test/tom/18'> </Link>
|
注册路由需要声明接收
1
| <Route path="demo/test/:name/:age" component={Test}>
|
接收参数
1
| const {name, age} = this.props.match.params
|
2.search参数
携带参数
1
| <Link to={`/home/?id=${msgObj.id}&title=${msgObj.title}`}></Link>
|
search参数无需声明接收
接收参数
1 2
| const {search} = this.props.location const res = qs.parse(search.slice(1))
|
使用 import qs from 'qs'用于将对象与urlencoded相互转换
如 user = {name: 'Tom', age: 18}
s = qs.stringify(user)
3.state参数
1
| <Link to={{pathname:'/home/message/detail',state:{id: msgObj.id, title: msgObj.title}}}></Link>
|
state参数无需声明接收