React路由
1 使用步骤
-
安装
npm install react-router-dom yarn add react-router-dom
-
导入路由核心组件
- 三个核心的组件:BrowserRouter、Route、Link
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
-
使用Router组件包裹整个应用(一个React应用只需要使用一次)。
- 两种常用的Router:HashRouter和BrowserRouter
- HashRouter:使用URL的哈希值实现。
- BrowserRouter:使用H5的history API实现。
- 两种常用的Router:HashRouter和BrowserRouter
-
使用Link组件指定路由入口(导航菜单)
- 用于指定导航链接(a标签)
- to属性:浏览器地址栏中的pathname
<Link to="/son1">子页面1</Link>
-
使用Route组件配置路由规则和路由出口(要展示的组件)
- Route组件结构展示在页面的区域,就是渲染出来的组件所在区域。
- path属性:路由规则
- component属性:展示的组件
const Son1 = () => <p>页面1内容</p> <Router> <div> <Link to="/son1">子页面1</Link> <Route path="/son1" component={Son1}></Route> </div> </Router>
2 React路由执行过程
React路由是怎么实现的呢?执行的是什么原理?
URL发生变化 —> 路由监听到URL变化 —> 路由遍历Route进行匹配 —> 展示组件内容
- 点击Link组件后,to属性(也就是a标签)修改了浏览第地址栏的URL。
- React路由监听到了地址栏URL的变化。
- React路由遍历内部所有的Route组件,将路由规则(path)与pathname进行匹配。
- 当匹配成功时,就展示当前Route组件的内容。
import React from 'react';
import ReactDOM from 'react-dom';
import './css/index.css'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
class Person extends React.Component {
render() {
return (
<Router>
<div className='parent'>
{/* 导航按钮 */}
<div className="top">
<p>Person页面</p>
<Link to="/son1">
<button>导航1</button>
</Link>
<Link to="/son2">
<button>导航2</button>
</Link>
</div>
{/* 目的界面 */}
<div className="two">
<div className="d1">
<Route path="/son1" component={Son1}></Route>
</div>
<div className="d2">
<Route path="/son2" component={Son2}></Route>
</div>
</div>
</div>
</Router>
)
}
}
class Son1 extends React.Component {
render() {
return (
<div className="son1">
<p>Son1页面</p>
</div >
)
}
}
class Son2 extends React.Component {
render() {
return (
<div className="son2">
<p>Son2页面</p>
</div >
)
}
}
ReactDOM.render(<Person></Person>, document.getElementById('root'))
3 编程式导航
- 概念:通过js代码实现页面跳转。
- 方法:
props.history.push('/son1')
—直接跳转到路由规则为son1的页面组件。props.hisory.go(-1)
—返回上一个页面组件。
- 精确匹配:使用属性
exact
实现路由精确匹配。
3.1 嵌套路由
- 在某组件中添加一个Route作为子路由(嵌套的路由)的出口。
- 设置嵌套路由的path,格式以父路由path为开头
- 父组件展示,子组件才会展示。
- 既展示父路由,又同时展示子嵌套路由。
import React from 'react';
import ReactDOM from 'react-dom';
import './css/index.css'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
class Person extends React.Component {
render() {
return (
<Router>
<div className='parent'>
{/* 导航按钮 */}
<div className="top">
<p>编程式导航</p>
<Link to="/son1">
<button>普通导航1</button>
</Link>
<Link to="/son2">
<button>普通导航2</button>
</Link>
</div>
{/* 目的界面 */}
<div className="two">
<div className="d1">
{/* 路由规则 */}
<Route path="/son1" component={Son1}></Route>
</div>
<div className="d2">
<Route path="/son2" component={Son2}></Route>
</div>
</div>
<div className="bian">
<div className="bian1">
<Route path="/son1/bian1" component={Bian1}></Route>
</div>
<div className="bian2">
<Route path="/son1/bian2" component={Bian2}></Route>
</div>
<div className="bian3">
<Route path="/son2/bian3" component={Bian3}></Route>
</div>
<div className="bian4">
<Route path="/son2/bian4" component={Bian4}></Route>
</div>
</div>
</div>
</Router>
)
}
}
class Son1 extends React.Component {
toBian1 = () => {
this.props.history.push('/son1/bian1')
}
toBian2 = () => {
this.props.history.push('/son1/bian2')
}
render() {
return (
<div className="son1">
<p>Son1页面</p>
<div>
<Router>
<Link to="/son1/bian1">
<button onClick={this.toBian1}>编程导航1</button>
</Link>
<Link to="/son1/bian2">
<button onClick={this.toBian2}>编程导航2</button>
</Link>
</Router>
</div>
</div >
)
}
}
class Son2 extends React.Component {
toBian3 = () => {
this.props.history.push('/son2/bian3')
}
toBian4 = () => {
this.props.history.push('/son2/bian4')
}
render() {
return (
<div className="son2">
<p>Son2页面</p>
<div>
<Router>
<Link to="/son2/bian3">
<button onClick={this.toBian3}>编程导航3</button>
</Link>
<Link to="/son2/bian4">
<button onClick={this.toBian4}>编程导航4</button>
</Link>
</Router>
</div>
</div >
)
}
}
// 编程式导航
class Bian1 extends React.Component {
goBack = () => {
this.props.history.go(-1)
}
render() {
return (
<div className="boxShadow">
<p>编程式导航1内容</p>
<button onClick={this.goBack}>返回</button>
</div >
)
}
}
class Bian2 extends React.Component {
goBack = () => {
this.props.history.go(-1)
}
render() {
return (
<div className="boxShadow">
<p>编程式导航2内容</p>
<button onClick={this.goBack}>返回</button>
</div >
)
}
}
class Bian3 extends React.Component {
goBack = () => {
this.props.history.go(-1)
}
render() {
return (
<div className="boxShadow">
<p>编程式导航3内容</p>
<button onClick={this.goBack}>返回</button>
</div >
)
}
}
class Bian4 extends React.Component {
goBack = () => {
this.props.history.go(-1)
}
render() {
return (
<div className="boxShadow">
<p>编程式导航4内容</p>
<button onClick={this.goBack}>返回</button>
</div >
)
}
}
ReactDOM.render(<Person></Person>, document.getElementById('root'))
/*index.css*/
*{
margin: 0;
padding: 0;
}
.parent {
width: 500px;
height: 500px;
margin: 50px;
text-align: center;
overflow: hidden;
background-color: rgba(250, 100, 0, 0.5);
}
.top{
width: 200px;
height: 50px;
background-color: #fa6400;
border-radius: 20px;
margin: 0 auto;
margin-top: 10px;
}
.son1,
.son2{
width: 100%;
height: 100%;
background-color: rgba(250, 100, 0, 0.8);
}
.two{
width: 500px;
height: 100px;
margin: 0 auto;
margin-top: 50px;
display: flex;
flex-direction: row;
}
.d1{
width: 250px;
height:300px;
}
.d2{
width: 250px;
height:300px;
}
.bian{
width: 500px;
height: 100px;
margin: 0 auto;
margin-top: 20px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.bian1,
.bian2,
.bian3,
.bian4{
width: 100%;
height: 100%;
text-align: center;
}
.boxShadow{
width: 120px;
height: 100px;
background-color: green;
color: #ffffff;
}