- 以下代码示例的参考代码只提供源码文件夹
/src
目录下的文件。 - 静态资源文件夹因为都一样,所以就不提供了,可以点击这里下载
public
目录。 - *代码的使用:根据步骤3.1.2执行完之后,替换掉相关文件夹即可。
5.1. 相关理解
中文文档
安装路由模块:npm i react-router-dom -S
路由的基本使用
-
明确好界面中的导航区、展示区
-
导航区的a标签改为Link标签
<Link to="/xxxxx">Demo</Link>
-
展示区写Route标签进行路径的匹配
<Route path='/xxxx' component={Demo}/>
-
<App>
的最外侧包裹了一个<BrowserRouter>
或<HashRouter>
路由组件与一般组件
-
写法不同:
一般组件:<Demo/>
路由组件:<Route path="/demo" component={Demo}/>
-
存放位置不同:
一般组件:components
路由组件:pages
-
接收到的props不同:
一般组件:写组件标签时传递了什么,就能收到什么
路由组件:接收到三个固定的属性history: go: ƒ go(n) goBack: ƒ goBack() goForward: ƒ goForward() push: ƒ push(path, state) replace: ƒ replace(path, state) // location: pathname: "/about" search: "" state: undefined // match: params: {} path: "/about" url: "/about"
5.1.1. SPA的理解
- 单页Web应用(single page web application,SPA)。
- 整个应用只有一个完整的页面。
- 点击页面中的链接不会刷新页面,只会做页面的局部更新。
- 数据都需要通过ajax请求获取, 并在前端异步展现。
5.1.2. 路由的理解
-
什么是路由?
-
一个路由就是一个映射关系(`key:value`)
-
`key`为路径, `value`可能是`function`或`component`
-
路由分类
-
后端路由:
1) 理解: `value`是`function`, 用来处理客户端提交的请求。
2) 注册路由:` router.get(path, function(req, res))`
3) 工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据 -
前端路由:
1) 浏览器端路由,`value`是`component`,用于展示页面内容。
2) 注册路由: `<Route path="/test" component={Test}>`
3) 作过程:当浏览器的`path`变为`/test`时, 当前路由组件就会变为Test组件
5.1.3. react-router-dom的理解
- react的一个插件库。
- 专门用来实现一个SPA应用。
- 基于react的项目基本都会用到此库。
5.2. react-router-dom相关API
5.2.1. 内置组件
- `<BrowserRouter>`
- `<HashRouter>`
- `<Route>`
- `<Redirect>`
- `<Link>`
- `<NavLink>`
- `<Switch>`
5.2.2. 其它
- history对象
- match对象
- withRouter函数
5.3. 基本路由使用
5.3.1. 效果
-
src/App.jsx
import React, { Component } from 'react' import {Link,Route} from 'react-router-dom' import Home from './components/Home' import About from './components/About' // export default class App extends Component { render() { return (
React Router Demo
{/* 注册路由 */} -
src/index.js
//引入react核心库 import React from 'react' //引入ReactDOM import ReactDOM from 'react-dom' // import {BrowserRouter} from 'react-router-dom' //引入App import App from './App' // ReactDOM.render(
-
src/components/About/index.jsx
import React, { Component } from 'react' // export default class About extends Component { render() { return (
我是About的内容
) } } -
src/components/Home/index.jsx
import React, { Component } from 'react' // export default class Home extends Component { render() { return (
我是Home的内容
) } }
5.3.2. 准备
- 下载react-router-dom: `npm install –save react-router-dom`
- 引入bootstrap.css: `<link rel="stylesheet" href="/css/bootstrap.css">`
5.4. 嵌套路由使用
-
src/App.jsx
import React, { Component } from 'react' import {Route,Switch,Redirect} from 'react-router-dom' import Home from './pages/Home' //Home是路由组件 import About from './pages/About' //About是路由组件 import Header from './components/Header' //Header是一般组件 import MyNavLink from './components/MyNavLink' // export default class App extends Component { render() { return (
{/* 注册路由 */} -
src/index.js
//引入react核心库 import React from 'react' //引入ReactDOM import ReactDOM from 'react-dom' // import {BrowserRouter} from 'react-router-dom' //引入App import App from './App' // ReactDOM.render(
-
src/components/Header/index.jsx
import React, { Component } from 'react' // export default class Header extends Component { render() { // console.log('Header组件收到的props是',this.props); return (
) } }React Router Demo
-
src/components/MyNavLink/index.jsx
import React, { Component } from 'react' import {NavLink} from 'react-router-dom' // export default class MyNavLink extends Component { render() { // console.log(this.props); return (
) } } -
src/pages/About/index.jsx
import React, { Component } from 'react' // export default class About extends Component { render() { // console.log('About组件收到的props是',this.props); return (
我是About的内容
) } } -
src/pages/Home/index.jsx
import React, { Component } from 'react' import MyNavLink from '../../components/MyNavLink' import {Route,Switch,Redirect} from 'react-router-dom' import News from './News' import Message from './Message' // export default class Home extends Component { render() { return (
我是Home的内容
-
News -
Message
-
-
src/pages/Home/Message/index.jsx
import React, { Component } from 'react' // export default class Message extends Component { render() { return ( ) } }
-
src/pages/Home/News/index.jsx
import React, { Component } from 'react' // export default class News extends Component { render() { return (
- news001
- news002
- news003
5.5. 向路由组件传递参数数据
5.5.1. 向路由组件传递params参数
-
src/App.jsx
import React, { Component } from 'react' import {Route,Switch,Redirect} from 'react-router-dom' import Home from './pages/Home' //Home是路由组件 import About from './pages/About' //About是路由组件 import Header from './components/Header' //Header是一般组件 import MyNavLink from './components/MyNavLink' // export default class App extends Component { render() { return (
{/* 注册路由 */} -
src/index.js
//引入react核心库 import React from 'react' //引入ReactDOM import ReactDOM from 'react-dom' // import {BrowserRouter} from 'react-router-dom' //引入App import App from './App' // ReactDOM.render(
-
src/components/Header/index.jsx
import React, { Component } from 'react' // export default class Header extends Component { render() { // console.log('Header组件收到的props是',this.props); return (
) } }React Router Demo
-
src/components/MyNavLink/index.jsx
import React, { Component } from 'react' import {NavLink} from 'react-router-dom' // export default class MyNavLink extends Component { render() { // console.log(this.props); return (
) } } -
src/pages/About/index.jsx
import React, { Component } from 'react' // export default class About extends Component { render() { // console.log('About组件收到的props是',this.props); return (
我是About的内容
) } } -
src/pages/Home/index.jsx
import React, { Component } from 'react' import MyNavLink from '../../components/MyNavLink' import {Route,Switch,Redirect} from 'react-router-dom' import News from './News' import Message from './Message' // export default class Home extends Component { render() { return (
我是Home的内容
-
News -
Message
-
-
src/pages/Home/Message/index.jsx
import React, { Component } from 'react' import {Link,Route} from 'react-router-dom' import Detail from './Detail' // export default class Message extends Component { state = { messageArr:[ {id:'01',title:'消息1'}, {id:'02',title:'消息2'}, {id:'03',title:'消息3'}, ] } render() { const {messageArr} = this.state return (
-
{
messageArr.map((msgObj)=>{
return (
- {/* 向路由组件传递params参数 */} /home/message/detail/${msgObj.id}/${msgObj.title}}>{msgObj.title} ) }) }
{/* 声明接收params参数 */} -
src/pages/Home/Message/Detail/index.jsx
import React, { Component } from 'react' // const DetailData = [ {id:'01',content:'你好,中国'}, {id:'02',content:'你好,硅谷'}, {id:'03',content:'你好,未来的自己'} ] export default class Detail extends Component { render() { console.log(this.props); // 接收params参数 const {id,title} = this.props.match.params const findResult = DetailData.find((detailObj)=>{ return detailObj.id === id }) return (
- ID:{id}
- TITLE:{title}
- CONTENT:{findResult.content}
-
src/pages/Home/News/index.jsx
import React, { Component } from 'react' // export default class News extends Component { render() { return (
- news001
- news002
- news003
5.5.2. 向路由组件传递search参数
-
src/App.jsx
和5.5.1 的文件一样 -
src/index.js
和5.5.1 的文件一样 -
src/components/Header/index.jsx
和5.5.1 的文件一样 -
src/components/MyNavLink/index.jsx
和5.5.1 的文件一样 -
src/pages/About/index.jsx
和5.5.1 的文件一样 -
src/pages/Home/index.jsx
import React, { Component } from 'react' import MyNavLink from '../../components/MyNavLink' import {Route,Switch,Redirect} from 'react-router-dom' import News from './News' import Message from './Message' // export default class Home extends Component { render() { return (
我是Home的内容
-
News -
Message
-
-
src/pages/Home/Message/index.jsx
import React, { Component } from 'react' import {Link,Route} from 'react-router-dom' import Detail from './Detail' // export default class Message extends Component { state = { messageArr:[ {id:'01',title:'消息1'}, {id:'02',title:'消息2'}, {id:'03',title:'消息3'}, ] } render() { const {messageArr} = this.state return (
-
{
messageArr.map((msgObj)=>{
return (
- {/* 向路由组件传递params参数 */} {/* /home/message/detail/${msgObj.id}/${msgObj.title}}>{msgObj.title} */} {/* 向路由组件传递search参数 */} /home/message/detail/?id=${msgObj.id}&title=${msgObj.title}}>{msgObj.title} ) }) }
{/* 声明接收params参数 */} {/**/} {/* search参数无需声明接收,正常注册路由即可 */} -
src/pages/Home/Message/Detail/index.jsx
import React, { Component } from 'react' import qs from 'querystring' // const DetailData = [ {id:'01',content:'你好,中国'}, {id:'02',content:'你好,硅谷'}, {id:'03',content:'你好,未来的自己'} ] // export default class Detail extends Component { render() { console.log(this.props); // 接收params参数 // const {id,title} = this.props.match.params // 接收search参数 const {search} = this.props.location const {id,title} = qs.parse(search.slice(1)) const findResult = DetailData.find((detailObj)=>{ return detailObj.id === id }) return (
- ID:{id}
- TITLE:{title}
- CONTENT:{findResult.content}
-
src/pages/Home/News/index.jsx
和5.5.1 的文件一样
5.5.3. 向路由组件传递state参数
-
src/App.jsx
和5.5.1 的文件一样 -
src/index.js
和5.5.1 的文件一样 -
src/components/Header/index.jsx
和5.5.1 的文件一样 -
src/components/MyNavLink/index.jsx
和5.5.1 的文件一样 -
src/pages/About/index.jsx
和5.5.1 的文件一样 -
src/pages/Home/index.jsx
import React, { Component } from 'react' import MyNavLink from '../../components/MyNavLink' import {Route,Switch,Redirect} from 'react-router-dom' import News from './News' import Message from './Message' // export default class Home extends Component { render() { return (
我是Home的内容
-
News -
Message
-
-
src/pages/Home/Message/index.jsx
import React, { Component } from 'react' import {Link,Route} from 'react-router-dom' import Detail from './Detail' // export default class Message extends Component { state = { messageArr:[ {id:'01',title:'消息1'}, {id:'02',title:'消息2'}, {id:'03',title:'消息3'}, ] } render() { const {messageArr} = this.state return (
-
{
messageArr.map((msgObj)=>{
return (
- {/* 向路由组件传递params参数 */} {/* /home/message/detail/${msgObj.id}/${msgObj.title}}>{msgObj.title} */} {/* 向路由组件传递search参数 */} {/* /home/message/detail/?id=${msgObj.id}&title=${msgObj.title}}>{msgObj.title} */} {/* 向路由组件传递state参数 */} {msgObj.title} ) }) }
{/* 声明接收params参数 */} {/**/} {/* search参数无需声明接收,正常注册路由即可 */} {/* */} {/* state参数无需声明接收,正常注册路由即可 */} -
src/pages/Home/Message/Detail/index.jsx
import React, { Component } from 'react' // import qs from 'querystring' // const DetailData = [ {id:'01',content:'你好,中国'}, {id:'02',content:'你好,硅谷'}, {id:'03',content:'你好,未来的自己'} ] // export default class Detail extends Component { render() { console.log(this.props); // 接收params参数 // const {id,title} = this.props.match.params // 接收search参数 // const {search} = this.props.location // const {id,title} = qs.parse(search.slice(1)) // 接收state参数 const {id,title} = this.props.location.state || {} const findResult = DetailData.find((detailObj)=>{ return detailObj.id === id }) || {} return (
- ID:{id}
- TITLE:{title}
- CONTENT:{findResult.content}
-
src/pages/Home/News/index.jsx
和5.5.1 的文件一样