开发单页面应用,基本都涉及到路由,何谓路由,简单来说,路由是根据不同的 url 地址展示不同的内容或页面。在前端开发中,要根据用户的操作去展示出不同的内容,我们通常采用路由解决,譬如,用户从主页点击到其它功能页时,点击相应链接按键后,我们就要跳转到相应的路由,路由发生改变后,页面的内容也发生改变。那么,在react中实现路由,首先要引入react-router模块,在项目目录下:
npm i react-router -D
如果需要Link组件配合跳转,需要安装react-router-dom
npm i react-router-dom -D
为了实现跳转的效果,创建两个组件
考虑到一个组件是一个页面,我创建在pages目录下,组件分别命名为Index和About。
在App.js文件下,引入组件并引路由需要的模块,代码如下:
import Index from './pages/index'
import About from './pages/about'
import { Router, Route } from 'react-router'
import { Link } from 'react-router-dom'
import createBrowserHistory from "history/createBrowserHistory"
const history = createBrowserHistory()
后面两句是创建一个路由的history对象,Router组件需要传入这个参数。接下来我将演示不同场景使用react-router。
场景一、点击跳转
点击上面的链接就跳转到相应的页面
写在App.js的代码如下:
class App extends Component {
render() {
return (
<div className="App">
<Router history={history}>
<div>
<Link to="/index" className="link">index</Link>
<Link to="/about" className="link">about</Link>
<hr></hr>
<div>
<Route path="/index" component={Index}/>
<Route path="/about" component={About}/>
</div>
</div>
</Router>
</div>
);
}
}
场景二、通过事件跳转路由
点击“切换页面”可以在两个组件之间不断地切换,这个切换是通过按钮的点击事件实现,代码改成以下:
class App extends Component {
exchangePage() {
let paths = ['/index', '/about']
let index = paths.indexOf(history.location.pathname)
history.push(paths[Math.abs(index - 1)])
}
render() {
return (
<div className="App">
<Router history={history}>
<div>
<button onClick={this.exchangePage}>切换页面</button>
<hr></hr>
<div>
<Route path="/index" component={Index}/>
<Route path="/about" component={About}/>
</div>
</div>
</Router>
</div>
);
}
}
在这里用到了"history/createBrowserHistory"创建的对象,我定义变量名history,hostory.push和hostory.replace方法可触发跳转,hostory.location可以查看路由的信息,hostory.location.pathname获取到当前路由的路径名。要实现页面的前进后退也是通过history对象来实现的。
场景三:路径传入参数
路径进入/about/:id后,将在组件内获取到传入的id值,在About组件里,代码改为:
class About extends Component{
render() {
return (<div>About 我是{this.props.match.params.id}</div>)
}
}
在App.js文件代码改为
render() {
return (
<div className="App">
<Router history={history}>
<div>
<button onClick={this.exchangePage}>切换页面</button>
<hr></hr>
<div>
<Route path="/index" component={Index}/>
<Route path="/about/:id" component={About}/>
</div>
</div>
</Router>
</div>
);
}
这种场景id是可以变化的,组件内根据不同的id选择展示不同的内容。
场景四:路由传数据
当需要通过路由将当前页面的一些数据传到下一个页面,或者根据请求时的参数显示不同的页面内容,这时将数据放在查询字段就可以了,查询的数据内容放在路径后面,前面有一个“?”
在About组件改为
class About extends Component{
render() {
return (<div>About {this.props.location.search}</div>)
}
}
场景五、子路由
在一个路由组件里面再插入一个路由,即路由的嵌套,就出现有子路由的情况。在这里一开始我还以为可以使用直接嵌套的方式去实现,然而并不可行,我暂时没有找到比较直接的方法,于是自己琢磨出一种方法实现。我在components目录中新建了一个Child组件,代码如下:
import React, { Component } from 'react'
class Child extends Component{
render() {
return (<div>我是子路由</div>)
}
}
export default Child
然后在App.js中引入,接着改写文件里面的内容,我修改的组件是About组件,修改后的代码如下:
<div className="App">
<Router history={history}>
<div>
<button onClick={this.exchangePage}>切换页面</button>
<hr></hr>
<div>
<Route path="/index" component={Index}/>
<Route path="/about/:name" children={({ match }) => {
const AboutChild = {
child: Child
}
const ChildContent = AboutChild[match.params.name]
return (
<About>
<ChildContent/>
</About>
)}}/>
</div>
</div>
</Router>
</div>
上面是根据url中name参数去匹配不同的组件,然后在About组件里,把子组件的内容,添加上去,代码如下:
class About extends Component{
render() {
return (<div>About {this.props.children}</div>)
}
}
在地址栏输入/about/child就得到以下的页面:
场景六:路由重定向
路由在某些时候是不允许访问,而是将页面跳转到另外一个路由去,先看代码:
import { Router, Route, Redirect } from 'react-router'
import createBrowserHistory from "history/createBrowserHistory"
const history = createBrowserHistory()
let isLogin = false
class App extends Component {
render() {
return (
<div className="App">
<Router history={history}>
<div>
<button onClick={this.exchangePage}>切换页面</button>
<hr></hr>
<div>
<Route path="/index" component={Index}/>
<Route path="/about" render={({match}) => (isLogin ? (<About/>) : (<Redirect to="/index"/> ))}/>
</div>
</div>
</Router>
</div>
);
}
}
这里我添加了一个变量isLogin,然后在path=“/about”的路由里根据isLogin的值是否跳转到about路径,如果isLogin为false时将重定向到“/index”(要把Redirect引进入)。
日常使用中,场景可能会有很多变,我在这只列出最基本的用法,要想把react-router用得好,得需要结合具体的场景和官方的最新文档。我的初次学习就先到这,以后有新发现会补充上去。