React路由
因为React也是单页面程序开发框架,所以其路由的实现也是通过hash的切换来完成,同时也需要使用对应的router依赖包
安装包
npm i react-router-dom@5 --save
配置路由
新建router文件夹,在内部新建index.js
然后我们再新建一个views文件夹,新建一个Home.js和About.js作为需要切换的页面使用
//BrowserRouter一个路由组件,该组件自带history模式,还有一个HashRouter,自带hash模式,但是不推荐使用
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Home from '../views/Home';
import About from '../views/About';
//react当中的路由管理对象是一个组件,所以我们这里采用函数组件编写
const Routers = () => {
return (
//表示该路由使用history模式
<BrowserRouter>
{/* 其作用类似switch判断语句 */}
<Switch>
{/* Route相当于vue中的路由单体对象 */}
{/* exact属性是作用精准匹配路由地址 */}
<Route exact path="/home" component={Home}></Route>
<Route exact path="/about" component={About}></Route>
</Switch>
</BrowserRouter>
)
}
export default Routers;
然后我们把路由组件导入到index.js入口文件中,再render内进行渲染,我们通过修改地址栏地址就可以完成一个基本的路由跳转效果了
注意:
在写路由组件的时候会有些不同的写法,有把路由组件导入到App顶层组件中,然后再在index.js中渲染App顶层组件来实现路由,还有直接就把App顶层组件直接改成路由组件使用,也有像上面例子中直接把路由组件在入口文件中渲染出来,然后把App顶层组件中的一个路由单体组件来看待
嵌套路由
嵌套路由其实就是对需要跳转的页面进行层级划分,现在我们根据之前vue项目中我们制作过的tabbar切换为例,来制作嵌套路由
进入router的index.js
//BrowserRouter一个路由组件,该组件自带history模式,还有一个HashRouter,自带hash模式,但是不推荐使用
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Home from '../views/Home';
import About from '../views/About';
import App from '../App';
//react当中的路由管理对象是一个组件,所以我们这里采用函数组件编写
const Routers = () => {
return (
<BrowserRouter>
<Switch>
<Route path="/" component={() => (
<App>
<Switch>
<Route path="/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
</Switch>
</App>
)}>
</Route>
</Switch>
</BrowserRouter>
)
}
export default Routers;
代码分析:
现在我们制作了一个指向根目录的一级路由对象,并将该路由对象跳转的目标页面设置为顶层组件App,而这里在注册App组件的时候使用的是一个函数的return方式,主要是为了在App虚拟标签的内部添加二级路由,在App组件内部再添加Switch因为在这之下会有不同页面需要切换,在Switch内部制作二级路由并把home和about注册到二级路由上
打开App.js,把原来的函数组件修改成类组件
import React, { Component } from 'react'
export default class App extends Component {
render() {
return (
<div>
home | about
<div>{this.props.children}</div>
</div>
)
}
}
代码分析:
this.props.children 这句话就相当是vue中router-view的作用,在App页面中可以切换显示home、about
路由跳转
现在我们可以通过手动输入地址栏切换页面,如何实现点击页面元素切换
1、Link标签:react-router-dom提供了一个Link组件可以实现页面
2、编程式导航:类似vue从路由对象中调用跳转方法执行跳转
打开App.js,通过link实现跳转
import React, { Component } from 'react'
import {Link} from 'react-router-dom' //导入link标签,通过link标签的to属性赋值路径实现跳转
export default class App extends Component {
render() {
return (
<div>
<Link to="/home">home</Link> | <Link to="/about">about</Link>
<div>{this.props.children}</div>
</div>
)
}
}
打开home.js或者about.js都行,实现编程式导航跳转
import React, { Component } from 'react'
export default class About extends Component {
//制作跳转方法
goToHome(){
//在props的history对象中包含了我们以前所熟知的各种页面跳转的方法
this.props.history.push("/home")
}
render() {
return (
<div>
about
<button onClick={this.goToHome.bind(this)}>跳转到home</button>
</div>
)
}
}
备注:
在props里面有很多有价值的东西,自己打印下props好好观察一下其内部结构,这里我们用到的history对象其实就可以理解成我们在BOM中学习过的history对象
返回上一页
打开home.js
import React, { Component } from 'react'
export default class Home extends Component {
UNSAFE_componentWillMount(){
console.log(this.props)
}
render() {
return (
<div>
home
<button onClick={this.back.bind(this)}>返回上一页</button>
</div>
)
}
back(){
//在props中包含了很多原生的BOM对象,其中就有history对象
this.props.history.goBack();
}
}
404页面
我们找一张网络404图片代表404页面,也可以自己写一个404页面,新建一个404组件
import React, { Component } from 'react'
export default class Page404 extends Component {
render() {
return (
<div>
<img src="https://img.zcool.cn/community/0196345ab31598a80121820775cbd1.png@2o.png" alt="" />
</div>
)
}
}
然后在router的index.js中新添加一个Route
//BrowserRouter一个路由组件,该组件自带history模式,还有一个HashRouter,自带hash模式,但是不推荐使用
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Home from '../views/Home';
import About from '../views/About';
import App from '../App';
import Page404 from '../views/Page404';
//react当中的路由管理对象是一个组件,所以我们这里采用函数组件编写
const Routers = () => {
return (
<BrowserRouter>
<Switch>
<Route path="/" component={() => (
<App>
<Switch>
<Route path="/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
<!-- 新增一个Route作为404页面的路由对象 -->
<Route component={Page404}></Route>
</Switch>
</App>
)}>
</Route>
</Switch>
</BrowserRouter>
)
}
export default Routers;
代码分析:
<Route component={Page404}></Route>
这里其实有点类似Switch语句的判断执行过程,用户在地址栏输入跳转路径,如果匹配到对应的path就跳转到对应的页面,如果没有就跳转到Page404
根路径跳转(重定向)
现在项目的根路径指向的是App.js组件,而这个组件内部除了tabber以外没有其他内容显示,所以我们需要将其重定向到其中某一个tabbar页面作为项目首页使用
打开App.js
import React, { Component } from 'react'
//再从react-router-dom中解构除withRouter
import {Link,withRouter} from 'react-router-dom'
class App extends Component {
render() {
return (
<div>
<Link to="/home">home</Link> | <Link to="/about">about</Link>
<div>{this.props.children}</div>
</div>
)
}
//当App组件准备挂载的时候
UNSAFE_componentWillMount(){
//判断当前浏览器地址的路由是否指向“/”
if(this.props.history.location.pathname === "/"){
//如果是就跳转到home页面
this.props.history.push("/home")
}
}
}
//导出App组件的时候通过withRouter,不然会获取不到路由对象,从而无法调用push
export default withRouter(App)
代码分析:
上面代码我们通过生命周期函数制作了一个重定向操作,其中withRouter是为了在挂载之前获取到路由对象调用push,而if判断是为了限制只有跳转到根路径的时候才重定向到home页面
页面传参
可以实现页面跳转之后,我们势必会在某些时候进行页面之间的数据互传,这里依然还式采用地址栏传参的方式,只不过react可以使用的页面传参的方式有三种:
1、在我们使用编程式导航跳转的时候,给跳转路径后面手动添加search
this.props.history.push("/home?str=haha")
然后可以通过之前我们在BOM中学习的原生写法来获取到search值
2、通过类似vue中params传参方式
this.props.history.push("/home/123")
然后到路由中home路径的路由子对象上设置
<Route path="/home/:id" component={Home}></Route>
在跳转目标页面中的 this.props.match.params
中即可找到传递来的参数
3、直接把需要传递的参数作为跳转方法的参数传入
this.props.history.push({
pathname:"/home",
state:{
num:15
}
})
这里的state对象中设置的就是当前页面要向目标页面传递的参数
然后我们可以在目标页面的 this.props.location.state
中可以找到传递的参数
注意:
上面三种传参方式,前两种都是显示传参可以在地址栏看到,第三种是隐式的地址栏看不到