[尚硅谷React笔记]——第5章 React 路由

目录:

  1. 对SPA应用的理解
  2. 对路由的理解
  3. 前端路由原理
  4. 路由的基本使用
  5. 路由组件与一般组件
  6. NavLink的使用
  7. 封装NavLink组件
  8. Switch的使用
  9. 解决样式丢失问题
  10. 路由的模糊匹配与严格匹配
  11. Redirect的使用
  12. 嵌套路由
  13. 向路由组件传递params参数
  14. 向路由组件传递search参数
  15. .向路由组件传递state参数
  16. 总结路由参数
  17. push与repalce
  18. 编程式路由导航
  19. withRouter的作用
  20. BrowserRouter与HashRouter

1.对SPA应用的理解

  1. 单页Web应用(single page web application,SPA)。
  2. 整个应用只有一个完整的页面
  3. 点击页面中的链接不会刷新页面,只会做页面的局部更新。
  4. 数据都需要通过ajax请求获取, 并在前端异步展现。

2.对路由的理解 

什么是路由?

  1. 一个路由就是一个映射关系(key:value)
  2. key为路径, value可能是function或component

路由分类

  1. 后端路由:
    1. 理解: value是function, 用来处理客户端提交的请求。
    2. 注册路由: router.get(path, function(req, res))
    3. 工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
  2. 前端路由:
    1. 浏览器端路由,value是component,用于展示页面内容。
    2. 注册路由: <Route path="/test" component={Test}>
    3. 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件

3.前端路由原理

前端路由的基石.html 

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>前端路由的基石_history</title>
</head>
<body>
	<a href="http://www.atguigu.com" onclick="return push('/test1') ">push test1</a><br><br>
	<button onClick="push('/test2')">push test2</button><br><br>
	<button onClick="replace('/test3')">replace test3</button><br><br>
	<button onClick="back()">&lt;= 回退</button>
	<button onClick="forword()">前进 =&gt;</button>

	<script type="text/javascript" src="https://cdn.bootcss.com/history/4.7.2/history.js"></script>
	<script type="text/javascript">
		// let history = History.createBrowserHistory() //方法一,直接使用H5推出的history身上的API
		let history = History.createHashHistory() //方法二,hash值(锚点)

		function push (path) {
			history.push(path)
			return false
		}

		function replace (path) {
			history.replace(path)
		}

		function back() {
			history.goBack()
		}

		function forword() {
			history.goForward()
		}

		history.listen((location) => {
			console.log('请求路由路径变化了', location)
		})
	</script>
</body>
</html>

 4.路由的基本使用

  1. 明确好界面中的导航区、展示区
  2. 导航区的a标签改为Link标签 <Link to="/xxxxx" >Demo</Link>
  3. 展示区写Route标签进行路径的匹配<Route path='/xxxx 'component={Demo}/>
  4. <App>的最外侧包裹了一个<BrowserRouter>或<HashRouter>

App.js

import React, {Component} from 'react';
import {Link, Route} from "react-router-dom";
import About from "./components/About/About";
import Home from "./components/Home/Home";

class App extends Component {
    render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-offset-2 col-xs-8">
                        <div className="page-header"><h2>React Router Demo</h2></div>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-2 col-xs-offset-2">
                        <div className="list-group">
                            <Link className="list-group-item" to="/about">About</Link>
                            <Link className="list-group-item" to="/home">Home</Link>
                        </div>
                    </div>
                    <div className="col-xs-6">
                        <div className="panel">
                            <div className="panel-body">
                                <Route path="/about" component={About}></Route>
                                <Route path="/home" component={Home}></Route>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter} from "react-router-dom";


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <BrowserRouter>
        <App/>
    </BrowserRouter>
);

About.jsx

import React, {Component} from 'react';

class About extends Component {
    render() {
        return (
            <div>
                <h3>我是About的内容</h3>
            </div>
        );
    }
}

export default About;

Home.jsx

import React, {Component} from 'react';

class Home extends Component {
    render() {
        return (
            <div>
                <h3>我是Home的内容</h3>
            </div>
        );
    }
}

export default Home;

运行结果:

5.路由组件与一般组件

  1. 写法不同:
    1. 一般组件: <Demo/ >
    2. 路由组件: <Route path="/demo" component={Demo}/>
  2. 存放位置不同:
    1. 一般组件:components
    2. 路由组件: pages
  3. 接收到的props不同:
    1. 一般组件:,写组件标签时传递了什么,就能收到什么
    2. 路由组件:接收到三个固定的属性
      1. history:
         
        1. go: f go(n)
        2. goBack: f goBack()
        3. goForward: f goForward()
        4. push: f push(path,state)
        5. replace: f replace(path, state)
      2. location:

        1. pathname: "/about"
        2. search: ""
        3. state: undefined
      3. match:|

        1. params: {}
        2. path: "/about"
        3. url: "/about"

 6.NavLink的使用

 Header.jsx

import React, {Component} from 'react';

class Header extends Component {
    render() {
        // console.log('Header组件收到的props是', this.props)
        return (
            <div>
                <div className="page-header"><h2>React Router Demo</h2></div>
            </div>
        );
    }
}

export default Header;

About.jsx

import React, {Component} from 'react';

class About extends Component {
    render() {
        // console.log('About组件收到的props是', this.props)
        return (
            <div>
                <h3>我是About的内容</h3>
            </div>
        );
    }
}

export default About;

Home.jsx

import React, {Component} from 'react';

class Home extends Component {
    render() {
        return (
            <div>
                <h3>我是Home的内容</h3>
            </div>
        );
    }
}

export default Home;

App.js

import React, {Component} from 'react';
import {NavLink, Route} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";

class App extends Component {
    render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-offset-2 col-xs-8">
                        <Header a={1}></Header>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-2 col-xs-offset-2">
                        <div className="list-group">
                            <NavLink activeClassName="atguigu" className="list-group-item" to="/about">About</NavLink>
                            <NavLink activeClassName="atguigu" className="list-group-item" to="/home">Home</NavLink>
                        </div>
                    </div>
                    <div className="col-xs-6">
                        <div className="panel">
                            <div className="panel-body">
                                <Route path="/about" component={About}></Route>
                                <Route path="/home" component={Home}></Route>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter} from "react-router-dom";


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <BrowserRouter>
        <App/>
    </BrowserRouter>
);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <meta name="theme-color" content="#000000"/>
    <meta
            name="description"
            content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png"/>
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json"/>
    <link rel="stylesheet" href="css/bootstrap.css">

    <style>
        .atguigu {
            background-color: orange !important;
            color: white !important;
        }
    </style>

    <title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

项目结构:

运行结果:

 7.封装NavLink组件

NavLink与封装NavLink

  1. NavLink可以实现路由链接的高亮,通过activeclassName指定样式名
  2. 标签体内容是一个特殊的标签属性
  3. 通过this.props.children可以获取标签体内容

 App.js

import React, {Component} from 'react';
import {NavLink, Route} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";

class App extends Component {
    render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-offset-2 col-xs-8">
                        <Header a={1}></Header>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-2 col-xs-offset-2">
                        <div className="list-group">
                            <MyNavLink to="/about" a={1} b={2} c={3}>About</MyNavLink>
                            <MyNavLink to="/home">Home</MyNavLink>
                        </div>
                    </div>
                    <div className="col-xs-6">
                        <div className="panel">
                            <div className="panel-body">
                                <Route path="/about" component={About}></Route>
                                <Route path="/home" component={Home}></Route>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter} from "react-router-dom";


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <BrowserRouter>
        <App/>
    </BrowserRouter>
);

Header.jsx

import React, {Component} from 'react';

class Header extends Component {
    render() {
        // console.log('Header组件收到的props是', this.props)
        return (
            <div>
                <div className="page-header"><h2>React Router Demo</h2></div>
            </div>
        );
    }
}

export default Header;

MyNavLink.jsx

import React, {Component} from 'react';
import {NavLink} from "react-router-dom";

class MyNavLink extends Component {
    render() {
        console.log(this.props)
        return (
            <div>
                <NavLink activeClassName="atguigu" className="list-group-item" {...this.props}/>
            </div>
        );
    }
}

export default MyNavLink;

About.jsx

import React, {Component} from 'react';

class About extends Component {
    render() {
        // console.log('About组件收到的props是', this.props)
        return (
            <div>
                <h3>我是About的内容</h3>
            </div>
        );
    }
}

export default About;

Home.jsx

import React, {Component} from 'react';

class Home extends Component {
    render() {
        return (
            <div>
                <h3>我是Home的内容</h3>
            </div>
        );
    }
}

export default Home;

项目结构:

运行结果:

 

8.Switch的使用

  1. 通常情况下,path和component是一一对应的关系。
  2. Switch可以提高路由匹配效率(单一匹配)。

Test.jsx

import React, {Component} from 'react';

class Test extends Component {
    render() {
        return (
            <div>
                <h2>Test...</h2>
            </div>
        );
    }
}

export default Test;

App.js

import React, {Component} from 'react';
import {NavLink, Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";
import Test from "./pages/Test/Test";

class App extends Component {
    render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-offset-2 col-xs-8">
                        <Header a={1}></Header>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-2 col-xs-offset-2">
                        <div className="list-group">
                            <MyNavLink to="/about" a={1} b={2} c={3}>About</MyNavLink>
                            <MyNavLink to="/home">Home</MyNavLink>
                        </div>
                    </div>
                    <div className="col-xs-6">
                        <div className="panel">
                            <div className="panel-body">
                                <Switch>
                                    <Route path="/about" component={About}></Route>
                                    <Route path="/home" component={Home}></Route>
                                    <Route path="/home" component={Test}></Route>
                                </Switch>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

运行结果:

项目结构:

9.解决样式丢失问题 

  1. public/index.html 中引入样式时不写./写/(常用)

  2. public/index.html 中引入样式时不写﹒/写%PUBLIC_URL%(常用)

  3. 使用HashRouter

1../css/bootstrap.css改为:

<link rel="stylesheet" href="css/bootstrap.css">

2../css/bootstrap.css改为:

<link rel="stylesheet" href="%PUBLIC_URL%/css/bootstrap.css">

3.BroserRouter改成HashRouter

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter, HashRouter} from "react-router-dom";


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <HashRouter>
        <App/>
    </HashRouter>
);

 10.路由的模糊匹配与严格匹配

  1. 默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
  2. 开启严格匹配:<Route exact={true} path="/about" component={About}/>
  3. 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由

 App.js

import React, {Component} from 'react';
import {Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";

class App extends Component {
    render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-offset-2 col-xs-8">
                        <Header a={1}></Header>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-2 col-xs-offset-2">
                        <div className="list-group">
                            <MyNavLink to="/about">About</MyNavLink>
                            <MyNavLink to="/home/a/b">Home</MyNavLink>
                        </div>
                    </div>
                    <div className="col-xs-6">
                        <div className="panel">
                            <div className="panel-body">
                                <Switch>
                                    <Route exact path="/about" component={About}></Route>
                                    <Route exact path="/home" component={Home}></Route>
                                </Switch>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

运行结果:

11.Redirect的使用

  1. 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
  2. 具体编码:
    <Switch>
    <Route path="/about" component={About}/>
    <Route path="/home" component={Home}/>
    <Redirect to="/about"/>
    </Switch>

App.js

import React, {Component} from 'react';
import {Redirect, Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";

class App extends Component {
    render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-offset-2 col-xs-8">
                        <Header a={1}></Header>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-2 col-xs-offset-2">
                        <div className="list-group">
                            <MyNavLink to="/about">About</MyNavLink>
                            <MyNavLink to="/home">Home</MyNavLink>
                        </div>
                    </div>
                    <div className="col-xs-6">
                        <div className="panel">
                            <div className="panel-body">
                                <Switch>
                                    <Route path="/about" component={About}></Route>
                                    <Route path="/home" component={Home}></Route>
                                    <Redirect to="/about"></Redirect>
                                </Switch>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

12.嵌套路由

  1. 注册子路由时要写上父路由的path值
  2. 路由的匹配是按照注册路由的顺序进行的

App.js

import React, {Component} from 'react';
import {Redirect, Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";

class App extends Component {
    render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-offset-2 col-xs-8">
                        <Header a={1}></Header>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-2 col-xs-offset-2">
                        <div className="list-group">
                            <MyNavLink to="/about">About</MyNavLink>
                            <MyNavLink to="/home">Home</MyNavLink>
                        </div>
                    </div>
                    <div className="col-xs-6">
                        <div className="panel">
                            <div className="panel-body">
                                <Switch>
                                    <Route path="/about" component={About}></Route>
                                    <Route path="/home" component={Home}></Route>
                                    <Redirect to="/about"></Redirect>
                                </Switch>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

Message.jsx

import React, {Component} from 'react';

class Message extends Component {
    render() {
        return (
            <div>
                <ul>
                    <li>
                        <a href="/message1">message001</a>&nbsp;&nbsp;
                    </li>
                    <li>
                        <a href="/message2">message002</a>&nbsp;&nbsp;
                    </li>
                    <li>
                        <a href="/message/3">message003</a>&nbsp;&nbsp;
                    </li>
                </ul>
            </div>
        );
    }
}

export default Message;

 News.jsx

import React, {Component} from 'react';

class News extends Component {
    render() {
        return (
            <div>
                <ul>
                    <li>news001</li>
                    <li>news002</li>
                    <li>news003</li>
                </ul>
            </div>
        );
    }
}

export default News;

Home.jsx

import React, {Component} from 'react';
import MyNavLink from "../../components/MyNavLink/MyNavLink";
import {Redirect, Route, Switch} from "react-router-dom";
import News from "./News/News";
import Message from "./Message/Message";

class Home extends Component {
    render() {
        return (
            <div>
                <h2>Home组件内容</h2>
                <div>
                    <ul className="nav nav-tabs">
                        <li>
                            <MyNavLink to="/home/news">News</MyNavLink>
                        </li>
                        <li>
                            <MyNavLink to="/home/message">Message</MyNavLink>
                        </li>
                    </ul>
                    <Switch>
                        <Route path="/home/news" component={News}></Route>
                        <Route path="/home/message" component={Message}></Route>
                        <Redirect to="/home/news"></Redirect>
                    </Switch>
                </div>
            </div>
        );
    }
}

export default Home;

MyNavLink.jsx

import React, {Component} from 'react';
import {NavLink} from "react-router-dom";

class MyNavLink extends Component {
    render() {
        console.log(this.props)
        return (
            <div>
                <NavLink activeClassName="atguigu" className="list-group-item" {...this.props}/>
            </div>
        );
    }
}

export default MyNavLink;

Header.jsx

import React, {Component} from 'react';

class Header extends Component {
    render() {
        // console.log('Header组件收到的props是', this.props)
        return (
            <div>
                <div className="page-header"><h2>React Router Demo</h2></div>
            </div>
        );
    }
}

export default Header;

About.jsx

import React, {Component} from 'react';

class About extends Component {
    render() {
        // console.log('About组件收到的props是', this.props)
        return (
            <div>
                <h3>我是About的内容</h3>
            </div>
        );
    }
}

export default About;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter, HashRouter} from "react-router-dom";


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <HashRouter>
        <App/>
    </HashRouter>
);

项目结构:

运行结果:

13. 向路由组件传递params参数

1.params参数

  • 路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
  • 注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
  • 接收参数: const {id,title} = this.props.match.params 

Header.jsx

import React, {Component} from 'react';

class Header extends Component {
    render() {
        // console.log('Header组件收到的props是', this.props)
        return (
            <div>
                <div className="page-header"><h2>React Router Demo</h2></div>
            </div>
        );
    }
}

export default Header;

MyNavLink.jsx

import React, {Component} from 'react';
import {NavLink} from "react-router-dom";

class MyNavLink extends Component {
    render() {
        console.log(this.props)
        return (
            <div>
                <NavLink activeClassName="atguigu" className="list-group-item" {...this.props}/>
            </div>
        );
    }
}

export default MyNavLink;

About.jsx

import React, {Component} from 'react';

class About extends Component {
    render() {
        // console.log('About组件收到的props是', this.props)
        return (
            <div>
                <h3>我是About的内容</h3>
            </div>
        );
    }
}

export default About;

Detail.jsx

import React, {Component} from 'react';

const DetailData = [
    {id: '01', content: '你好,中国'},
    {id: '02', content: '你好,尚硅谷'},
    {id: '03', content: '你好,未来的自己'},
]

class Detail extends Component {

    render() {
        // console.log(this.props)
        const {id, title} = this.props.match.params
        const findResult = DetailData.find((detailObj) => {
            return detailObj.id === id
        })
        return (
            <ul>
                <li>ID:{id}</li>
                <li>TITLE:{title}</li>
                <li>CONTENT:{findResult.content}</li>
            </ul>
        );
    }
}

export default Detail;

Message.jsx

import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";

class Message extends Component {
    state = {
        messageArr: [
            {id: '01', title: '消息1'},
            {id: '02', title: '消息2'},
            {id: '03', title: '消息3'},
        ]
    }

    render() {
        const {messageArr} = this.state
        return (
            <div>
                <ul>
                    {
                        messageArr.map((msgObj) => {
                            return (
                                <li key={msgObj.id}>
                                    <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
                                </li>
                            )
                        })
                    }
                </ul>

                <hr></hr>
                <Route path="/home/message/detail/:id/:title" component={Detail}></Route>
            </div>
        );
    }
}

export default Message;

News.jsx

import React, {Component} from 'react';

class News extends Component {
    render() {
        return (
            <div>
                <ul>
                    <li>news001</li>
                    <li>news002</li>
                    <li>news003</li>
                </ul>
            </div>
        );
    }
}

export default News;

Home.jsx 

import React, {Component} from 'react';
import MyNavLink from "../../components/MyNavLink/MyNavLink";
import {Redirect, Route, Switch} from "react-router-dom";
import News from "./News/News";
import Message from "./Message/Message";

class Home extends Component {
    render() {
        return (
            <div>
                <h2>Home组件内容</h2>
                <div>
                    <ul className="nav nav-tabs">
                        <li>
                            <MyNavLink to="/home/news">News</MyNavLink>
                        </li>
                        <li>
                            <MyNavLink to="/home/message">Message</MyNavLink>
                        </li>
                    </ul>
                    <Switch>
                        <Route path="/home/news" component={News}></Route>
                        <Route path="/home/message" component={Message}></Route>
                        <Redirect to="/home/news"></Redirect>
                    </Switch>
                </div>
            </div>
        );
    }
}

export default Home;

App.js

import React, {Component} from 'react';
import {Redirect, Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";

class App extends Component {
    render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-offset-2 col-xs-8">
                        <Header a={1}></Header>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-2 col-xs-offset-2">
                        <div className="list-group">
                            <MyNavLink to="/about">About</MyNavLink>
                            <MyNavLink to="/home">Home</MyNavLink>
                        </div>
                    </div>
                    <div className="col-xs-6">
                        <div className="panel">
                            <div className="panel-body">
                                <Switch>
                                    <Route path="/about" component={About}></Route>
                                    <Route path="/home" component={Home}></Route>
                                    <Redirect to="/about"></Redirect>
                                </Switch>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter, HashRouter} from "react-router-dom";


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <HashRouter>
        <App/>
    </HashRouter>
);

运行结果:

项目结构:

 

14.向路由组件传递search参数

2.search参数

  • 路由链接(携带参数): <Link to=' /demo/test?name=tom&age=18'}>详情</Link>
  • 注册路由(无需声明,正常注册即可): <Route path="/demo/test" component={Test}/>
  • 接收参数: const isearch} = this.props.location
  • 备注:获取到的search是urlencoded编码字符串,需要借助querystring解析

Message.jsx

import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";

class Message extends Component {
    state = {
        messageArr: [
            {id: '01', title: '消息1'},
            {id: '02', title: '消息2'},
            {id: '03', title: '消息3'},
        ]
    }

    render() {
        const {messageArr} = this.state
        return (
            <div>
                <ul>
                    {
                        messageArr.map((msgObj) => {
                            return (
                                <li key={msgObj.id}>
                                    {/*<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>*/}
                                    <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
                                </li>
                            )
                        })
                    }
                </ul>

                <hr></hr>
                {/*<Route path="/home/message/detail/:id/:title" component={Detail}></Route>*/}
                <Route path="/home/message/detail" component={Detail}></Route>
            </div>
        );
    }
}

export default Message;

Detail.jsx

import React, {Component} from 'react';
import qs from "qs"

const DetailData = [
    {id: '01', content: '你好,中国'},
    {id: '02', content: '你好,尚硅谷'},
    {id: '03', content: '你好,未来的自己'},
]

class Detail extends Component {

    render() {
        console.log(this.props)
        // const {id, title} = this.props.match.params

        const {search} = this.props.location
        const {id, title} = qs.parse(search.slice(1))
        const findResult = DetailData.find((detailObj) => {
            return detailObj.id === id
        })
        return (
            <ul>
                <li>ID:{id}</li>
                <li>TITLE:{title}</li>
                <li>CONTENT:{findResult.content}</li>
            </ul>
        );
    }
}

export default Detail;

运行结果:

项目结构:

15.向路由组件传递state参数

state参数:

  • 路由链接(携带参数): <Link to={{path:' /demo/test',state:{name : ' tom' ,age:18]}}>详情</Link>注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
  • 接收参数: this.props.location.state
  • 备注:刷新也可以保留住参数

 Message.jsx

import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";

class Message extends Component {
    state = {
        messageArr: [
            {id: '01', title: '消息1'},
            {id: '02', title: '消息2'},
            {id: '03', title: '消息3'},
        ]
    }

    render() {
        const {messageArr} = this.state
        return (
            <div>
                <ul>
                    {
                        messageArr.map((msgObj) => {
                            return (
                                <li key={msgObj.id}>
                                    {/*<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>*/}
                                    {/*<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>*/}
                                    <Link to={{
                                        pathname: '/home/message/detail',
                                        state: {id: msgObj.id, title: msgObj.title}
                                    }}>{msgObj.title}</Link>
                                </li>
                            )
                        })
                    }
                </ul>

                <hr></hr>
                {/*<Route path="/home/message/detail/:id/:title" component={Detail}></Route>*/}
                {/*<Route path="/home/message/detail" component={Detail}></Route>*/}
                <Route path="/home/message/detail" component={Detail}></Route>
            </div>
        );
    }
}

export default Message;

Detail.jsx

import React, {Component} from 'react';
import qs from "qs"

const DetailData = [
    {id: '01', content: '你好,中国'},
    {id: '02', content: '你好,尚硅谷'},
    {id: '03', content: '你好,未来的自己'},
]

class Detail extends Component {

    render() {
        console.log(this.props)
        // const {id, title} = this.props.match.params

        // const {search} = this.props.location
        // const {id, title} = qs.parse(search.slice(1))


        const {id, title} = this.props.location.state || {}

        const findResult = DetailData.find((detailObj) => {
            return detailObj.id === id
        }) || {}
        return (
            <ul>
                <li>ID:{id}</li>
                <li>TITLE:{title}</li>
                <li>CONTENT:{findResult.content}</li>
            </ul>
        );
    }
}

export default Detail;

运行结果:

16.总结路由参数

17.push与repalce 

Message.jsx

import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";

class Message extends Component {
    state = {
        messageArr: [
            {id: '01', title: '消息1'},
            {id: '02', title: '消息2'},
            {id: '03', title: '消息3'},
        ]
    }

    render() {
        const {messageArr} = this.state
        return (
            <div>
                <ul>
                    {
                        messageArr.map((msgObj) => {
                            return (
                                <li key={msgObj.id}>
                                    {/*<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>*/}
                                    {/*<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>*/}
                                    <Link replace={true} to={{
                                        pathname: '/home/message/detail',
                                        state: {id: msgObj.id, title: msgObj.title}
                                    }}>{msgObj.title}</Link>
                                </li>
                            )
                        })
                    }
                </ul>

                <hr></hr>
                {/*<Route path="/home/message/detail/:id/:title" component={Detail}></Route>*/}
                {/*<Route path="/home/message/detail" component={Detail}></Route>*/}
                <Route path="/home/message/detail" component={Detail}></Route>
            </div>
        );
    }
}

export default Message;
  • push:留下记录
  • repalce:不留记录

18.编程式路由导航 

Message.jsx

import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";

class Message extends Component {
    state = {
        messageArr: [
            {id: '01', title: '消息1'},
            {id: '02', title: '消息2'},
            {id: '03', title: '消息3'},
        ]
    }

    render() {
        const {messageArr} = this.state
        return (
            <div>
                <ul>
                    {
                        messageArr.map((msgObj) => {
                            return (
                                <li key={msgObj.id}>
                                    {/*<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>*/}
                                    {/*<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>*/}
                                    <Link replace={true} to={{
                                        pathname: '/home/message/detail',
                                        state: {id: msgObj.id, title: msgObj.title}
                                    }}>{msgObj.title}</Link>
                                </li>
                            )
                        })
                    }
                </ul>

                <hr></hr>
                {/*<Route path="/home/message/detail/:id/:title" component={Detail}></Route>*/}
                {/*<Route path="/home/message/detail" component={Detail}></Route>*/}
                <Route path="/home/message/detail" component={Detail}></Route>
            </div>
        );
    }
}

export default Message;

 Detail.jsx

import React, {Component} from 'react';
import qs from "qs"

const DetailData = [
    {id: '01', content: '你好,中国'},
    {id: '02', content: '你好,尚硅谷'},
    {id: '03', content: '你好,未来的自己'},
]

class Detail extends Component {

    render() {
        console.log(this.props)
        // const {id, title} = this.props.match.params

        // const {search} = this.props.location
        // const {id, title} = qs.parse(search.slice(1))


        const {id, title} = this.props.location.state || {}

        const findResult = DetailData.find((detailObj) => {
            return detailObj.id === id
        }) || {}
        return (
            <ul>
                <li>ID:{id}</li>
                <li>TITLE:{title}</li>
                <li>CONTENT:{findResult.content}</li>
            </ul>
        );
    }
}

export default Detail;

 19.withRouter的作用

News.jsx

import React, {Component} from 'react';

class News extends Component {
    componentDidMount() {
        setTimeout(() => {
            this.props.history.push('/home/message')
        }, 2000)
    }

    render() {
        return (
            <div>
                <ul>
                    <li>news001</li>
                    <li>news002</li>
                    <li>news003</li>
                </ul>
            </div>
        );
    }
}

export default News;
  • 借助this.prosp.history对象上的API对操作路由跳转、前进、后退
  • this.prosp.history.push()
  • this.prosp.history.replace()
  • this.prosp.history.goBack()
  • this.prosp.history.goForward()
  • this.prosp.history.go()

 

  1. withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
  2. withRouter的返回值是一个新组件 

Header.jsx

import React, {Component} from 'react';
import {withRouter} from "react-router-dom";


class Header extends Component {
    back = () => {
        this.props.history.goBack()
    }
    forward = () => {
        this.props.history.goForward()
    }
    go = () => {
        this.props.history.go(2)
    }

    render() {
        // console.log('Header组件收到的props是', this.props)
        return (
            <div>
                <div className="page-header">
                    <h2>React Router Demo</h2>
                    <button onClick={this.back}>回退</button>
                    <button onClick={this.forward}>前进</button>
                    <button onClick={this.go}>go</button>
                </div>
            </div>
        );
    }
}

export default withRouter(Header);

20.BrowserRouter与HashRouter

  • 1.底层原理不一样:
    • BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
    • HashRouter使用的是URL的哈希值
  • 2.path表现形式不一样
    • BrowserRouter的路径中没有#,例如: localhost:3000/demo/test
    • HashRouter的路径包含#,例如: localhost:3000/#/demo/test
  • 3.刷新后对路由state参数的影响
    • (1).BrowserRouter没有任何影响,因为state保存在history对象中。
    • (2).HashRouter刷新后会导致路由state参数的丢失。
  • 4.备注: HashRouter可以用于解决一些路径错误相关的问题。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿瞒有我良计15

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值