一、项目初始化准备
1、创建与启动
- npx create-react-app react-router
- cd react-router
- yarn start 或 npm start 或 npm run start
- 新建 src/components/ComRouter.js
- yarn add react-router-dom@5.2.1
特别注意:如果是 react-router-dom 的版本过高,写法会有所变化。
2、保留 index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)
3、App.js
import React from 'react'
// 导入 ComRouter 组件
import ComRouter from './components/ComRouter'
class App extends React.Component {
render() {
return <div>
<ComRouter></ComRouter>
</div>
}
}
export default App
二、路由初体验
1、在ComRouter.js 中 log 一下 路由里面的东西
import React from 'react'
// yarn add react-router-dom@5.2.1
import * as obj from 'react-router-dom'
class ComRouter extends React.Component {
render() {
console.log(obj,'路由呀')
return <div>
<p>我是 ComRouter</p>
</div>
}
}
export default ComRouter
2、查看打印结果,先自己摸索一下
3、重点数据说明
- BrowserRouter :history 路由
- HashRouter :hash 路由
- Link :相当于 vue 中的 router-link
- to 属性,将来会渲染成 a 标签的 href 属性
Link组件无法实现导航的高亮效果
- Route :相当于 vue 中的 router-view
- NavLink :一个更特殊的
Link组件,可以用于指定当前导航高亮- to属性 :用于指定地址,会渲染成 a 标签的 href 属性
- activeClass :用于指定高亮的类名,默认
active - exact :精确匹配,表示必须精确匹配类名才生效
4、在ComRouter.js 开始配置一级路由测试一下
import React from 'react'
// 导入 react-router-dom
import { BrowserRouter, Link, Route } from 'react-router-dom'
// 配置一级路由
const First = () => {
return <div>
编程不仅仅是技术,还是艺术!First
</div>
}
const Second = () => {
return <div>
编程不仅仅是技术,还是艺术!Second
</div>
}
const Third = () => {
return <div>
编程不仅仅是技术,还是艺术!Third
</div>
}
// ◆ BrowserRouter 只能出现一次
class ComRouter extends React.Component {
render() {
return <div>
<p>我是 ComRouter</p>
<BrowserRouter>
<ul>
<li><Link to='/first'>我是 first</Link></li>
<li><Link to='/second'>我是 second</Link></li>
<li><Link to='/third'>我是 third</Link></li>
</ul>
<div className="box">
<Route path="/first" component={First}></Route>
<Route path="/second" component={Second}></Route>
<Route path="/third" component={Third}></Route>
</div>
</BrowserRouter>
</div>
}
}
export default ComRouter
三、路由进阶
1、进阶需求:
- 实现导航高亮
NavLink - 路由重定向到
First组件 - 实现
404页面
2、引入Switch 组件 和 exact 属性
- 通常,我们会把
Route包裹在一个Switch组件中 - 在
Switch组件中,不管有多少个路由规则匹配到了,都只会渲染第一个匹配的组件 - 通过
Switch组件非常容易的就能实现404错误页面的提示 Route设置exact属性, 实现精确匹配
3、新建 src/index.css 设置导航高亮的样式
.active {
background-color: pink;
}
4、开始改装 ComRouter.js
import React from 'react'
// ◆ 导入 样式
import '../index.css'
// ◆ 导入 react-router-dom
import { BrowserRouter, NavLink, Route, Switch ,Redirect} from 'react-router-dom'
const First = () => {
return <div>
编程不仅仅是技术,还是艺术!First
</div>
}
const Second = () => {
return <div>
编程不仅仅是技术,还是艺术!Second
</div>
}
const Third = () => {
return <div>
编程不仅仅是技术,还是艺术!Third
</div>
}
// ◆ 404 页面
const NotFound = () => {
return <div>
404 NOTFOUND
</div>
}
class ComRouter extends React.Component {
render() {
return <div>
<p>我是 ComRouter</p>
<BrowserRouter>
<ul>
{/* ◆ 导航高亮 NavLink */}
<li><NavLink to='/first'>我是 first</NavLink></li>
<li><NavLink to='/second'>我是 second</NavLink></li>
<li><NavLink to='/third'>我是 third</NavLink></li>
</ul>
<div className="box">
<Switch>
{/* <Route exact path="/" component={First}></Route> */}
{/* ◆ 路由重定向 */}
<Redirect exact from="/" to="/First"></Redirect>
<Route path="/first" component={First}></Route>
<Route path="/second" component={Second}></Route>
<Route path="/Third" component={Third}></Route>
{/* ◆ 404页面 */}
<Route component={NotFound}></Route>
</Switch>
</div>
</BrowserRouter>
</div>
}
}
export default ComRouter
四、再度进阶
1、进阶需求
- 抽离各个组件为单独的
js文件 - 实现二级路由跳转:Second 下新增:Web、Java、Ui 页面
2、新建一级路由文件夹及相关文件
- src/components/Pages/First.js
- src/components/Pages/Second.js
- src/components/Pages/Third.js
- src/components/Pages/NotFound.js
3、一级路由内容(初始调整)
First.js 还是函数组件
import React from 'react'
const First = () => {
return <div>
编程不仅仅是技术,还是艺术!First
</div>
}
export default First
Second.js 调整为类组件
import React from 'react'
class Second extends React.Component {
render() {
return <div>
编程不仅仅是技术,还是艺术!Second
</div>
}
}
export default Second
Third.js 调整为类组件
import React from 'react'
class Third extends React.Component {
render() {
return <div>
编程不仅仅是技术,还是艺术!Third
</div>
}
}
export default Third
NotFound.js 还是函数组件
const NotFound = () => {
return <div>
404 NOTFOUND
</div>
}
export default NotFound
ComRouter.js 导入
import React from 'react'
// 导入 样式
import '../index.css'
// 导入 react-router-dom
import { BrowserRouter, NavLink, Route, Switch } from 'react-router-dom'
// 导入
import First from './Pages/First'
import Second from './Pages/Second'
import Third from './Pages/Third'
import NotFound from './Pages/NotFound'
class ComRouter extends React.Component {
render() {
return <div>
<p>我是 ComRouter</p>
<BrowserRouter>
<ul>
<li><NavLink to='/first'>我是 first</NavLink></li>
<li><NavLink to='/second'>我是 second</NavLink></li>
<li><NavLink to='/third'>我是 third</NavLink></li>
</ul>
<div className="box">
<Switch>
<Route exact path="/" component={First}></Route>
<Route path="/first" component={First}></Route>
<Route path="/second" component={Second}></Route>
<Route path="/Third" component={Third}></Route>
<Route component={NotFound}></Route>
</Switch>
</div>
</BrowserRouter>
</div>
}
}
export default ComRouter
4、配置二级路由
1.新建二级路由文件夹及文件
- src/components/Pages/Second/Web.js
- src/components/Pages/Second/Java.js
- src/components/Pages/Second/Ui.js
2.二级路由内容
Web.js
const Web =()=>{
return <div>我是 Web</div>
}
export default Web
Java.js
const Java =()=>{
return <div>我是 Java
</div>
}
export default Java
Ui.js
const Ui =()=>{
return <div>我是 Ui</div>
}
export default Ui
3.改装 Second.js
import React from 'react'
// 导入 react-router-dom
import { Link, Route, Switch } from 'react-router-dom'
// 导入二级路由组件
import Web from './Second/Web'
import Java from './Second/Java'
import Ui from './Second/Ui'
class Second extends React.Component {
render() {
return <div>
编程不仅仅是技术,还是艺术!Second
<ul >
<li><Link to='/second/web'>web</Link></li>
<li><Link to='/second/java'>java</Link></li>
<li><Link to='/second/ui'>ui</Link></li>
</ul>
<div className="box">
<Switch>
<Route path="/second/web" component={Web}></Route>
<Route path="/second/java" component={Java}></Route>
<Route path="/second/ui" component={Ui}></Route>
</Switch>
</div>
</div>
}
}
export default Second
五、传参及获参
第一种方法:search
1.Second.js 传递参数
// 省略其他。。。
<li><Link to='/second/web?name=Lucy&age=18'>web</Link></li>
2.Web.js 获取参数
const Web = (props) => {
console.log(props, 'Web')
// console.log(props,'路由传参web')
console.log(props.location.search)//?name=Lucy&age=18
// 如果我们想获取 name 和 age,怎么办?
// ◆法1:浏览器内置的方法 new URLSearchParams()
const name = new URLSearchParams(props.location.search).get('name')
const age = new URLSearchParams(props.location.search).get('age')
console.log(name)// Lucy
console.log(age)// 18
// ◆法2:slice()方法,可用于字符串和数组(我还想变成对象的格式)
// 1.把问号去掉
const query = props.location.search.slice(1)
console.log(query, 'query')// name=Lucy&age=18
// 2.切割成数组
const arr = query.split('&')
console.log(arr, 'res')// 'name=Lucy', 'age=18'] 'res'
// 3.再循环切割获取对象
let obj = {}
arr.forEach(item => {
const arr2 = item.split(['='])
console.log(arr2, 'arr2')// ['name','Lucy'] ['age','18']
obj[arr2[0]] = arr2[1]
})
console.log(obj, 'obj')// {name: 'Lucy', age: '18'}
// ◆法3:把 法2 封装成函数
function paramsQuery(url) {
// 1.把问号去掉
const query = url.slice(1)
// 2.切割成数组
const arr = query.split('&')
// 3.再循环切割获取对象
let newObj = {}
arr.forEach(item => {
const arr2 = item.split(['='])
newObj[arr2[0]] = arr2[1]
})
// const {name,age}=obj
// 4.返回对象
return newObj
}
// 5.调用获取结果
const res = paramsQuery(props.location.search)
console.log(res, '123')
// ◆显示在页面
return <div>我是 Web
{/* 法1:利用浏览器内置方法*/}
<p>我的名字是:{name} 我的年龄是:{age}</p>
{/* 法2:截取、切割、循环 */}
<p>我的名字是:{obj.name} 我的年龄是:{obj.age}</p>
{/* 法3:封装成函数 */}
<p>我的名字是:{res.name} 我的年龄是:{res.age}</p>
</div>
}
export default Web
第二种方法:params (附带 search )
1.Second.js 传递参数
// 省略其他。。。
<li><Link to='/second/java/2/rose?age=25'>java</Link></li>
<Route path="/second/java/:id/:name" component={Java}></Route>
2.Java.js 获取参数
const Java = (props) => {
// 1.接收 params 参数
const id = props.match.params.id
const name = props.match.params.name
// 2.接收 search 参数
console.log(props.location.search, 'Java')// ?age=25
const age = new URLSearchParams(props.location.search).get('age')
// 3.显示在页面
return <div>我是 Java
<p>我的id 是{id},我的名字是{name}</p>
<p>我的年龄是{age}</p>
</div>
}
export default Java
第三种方法:query
1.Second.js 传递参数
<li><Link to={{pathname:'/second/ui',query:{name:'Jack'}}}>ui</Link></li>
2.Ui.js 获取参数
const Ui = (props) => {
console.log(props, 'Ui')
// 1.获取 query 参数
const name = props.location.query.name
// 2.显示在页面
return <div>我是 Ui
<p>我的名字是 {name}</p>
</div>
}
export default Ui
第四种方法:state(类似 query)
1.Second.js 传递参数
{/* <li><Link to={{pathname:'/second/ui',query:{name:'Jack'}}}>ui</Link></li> */}
<li><Link to={{pathname:'/second/ui',state:{name:'Mini'}}}>ui</Link></li>
2.Ui.js 获取参数
const Ui = (props) => {
console.log(props, 'Ui')
// 1.获取 query 参数
// const name = props.location.query.name
// 1.获取 state 参数
const name = props.location.state.name
// 2.显示在页面
return <div>我是 Ui
<p>我的名字是 {name}</p>
</div>
}
export default Ui