路由的理解
- 1)什么是路由?
a. 一个路由就是一个映射关系(key:value)
b. key为路由路径, value可能是function/component - 2)路由分类
a. 后台路由: node服务器端路由, value是function, 用来处理客户端提交的请求并返回一个响应数据
b. 前台路由: 浏览器端路由, value是component, 当请求的是路由path时, 浏览器端前没有发送http请求, 但界面会更新显示对应的组件 - 3)后台路由
a. 注册路由:router.get(path, function(req, res))
b. 当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据 - 4)前端路由
a. 注册路由:<Route path="/about" component={About}>
b. 当浏览器的hash变为/about时, 当前路由组件就会变为About组件
react-router相关API
react-router是伴随着react框架出现的路由系统,它也是公认的一种优秀的路由解决方案。在使用react-router时候,我们常常会使用其自带的路径跳转组件Link
,通过<Link to="path"></Link>
实现跳转,这和传统的<a href="path"></a>
何其相似!但它们到底有什么具体的区别呢
对比<a>
,Link
组件避免了不必要的重渲染react-router
:只更新变化的部分从而减少DOM性能消耗
组件
- 1)
路由方案,路由方案的一种形式 browserHistory
使用的是HTML5
的pushState
API来修改浏览器的历史记录
需要服务器端做配置,路径是真实的URL,是官方推荐首选
为什么browserHistory
需要服务端配置?,因为真实URL其实是指向服务器资源,比如我们经常使用的API接口,也是一个真实URL的资源路径,当通过真实URL访问网站的时候,第一次访问的是网站的域名,这个时候可以正常加载我们的网站js等文件,而用户手动刷新网页时,由于路径是指向服务器的真实路径,服务器端没有做路由配置,就会导致资源不存在,用户访问的资源不存在,返回给用户的是404错误。
通过hashHistory
来生成的URL就不会出现这样的问题,因为他不是指向真实的路由
两种方式的特点
1.History API 提供了pushState()
和replaceState()
方法来增加或替换历史记录。而hash
没有相应的方法,所以browserHistory
有替换历史记录的功能,hashHistory
没有
2.hashHistory
实现简单,不需要做额外的服务端改造 -
2)
<HashRouter>
hashHistory 是通过改变地址后面的 hash(也就是URL中#后面的值) 来改变浏览器的历史记录
不需要服务器配置,在URL生成一个哈希来跟踪状态,通常在测试环境使用,也可以作为发布环境使用 -
3)
<Route>
路由组件,注册路由
Route组件的Props对象中包含有path和component两个属性
path属性:URL的路径
component属性: 当匹配到 URL 时,单个的组件会被渲染。它可以 被父route
组件的this.props.children
渲染 -
4)
<Router>
路由器组件,用来包含各个路由器组件,管理路由器 -
5)
<Redirect>
标签通过自动重写URL来将浏览器重定向至一个新的URL -
6)
<Link>
路由链接组件,生成a标签的,<Link>
时,url会更新,组件会被重新渲染,但是页面不会重新加载 -
7)
<NavLink>
是<Link>
的一个特定版本,会在匹配上当前的url的时候给已经渲染的元素添加参数,组件的属性有activeClassName(string)
:设置选中样式,默认值为activeactiveStyle(object)
:当元素被选中时,为此元素添加样式exact(bool)
:为true时,只有当导致和完全匹配class和style才会应用strict(bool)
:为true时,在确定为位置是否与当前URL匹配时,将考虑位置pathname后的斜线 -
8)
有 标签,则其中的 在路径相同的情况下,只匹配第一个,这个可以避免重复匹配
基本路由使用
-
实现效果:
-
静态html下载
点击下载 -
安装react-router
yarn add react-router-dom
index.js
代码:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import {BrowserRouter} from 'react-router-dom'
ReactDOM.render(
<BrowserRouter>
<App/>
</BrowserRouter>,
document.getElementById('root')
)
App.jsx
代码:
import React, {Component} from "react"
import {NavLink, Route, Redirect, Switch} from 'react-router-dom'
import About from "./pages/About"
import Home from './pages/Home'
export default 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">
<NavLink className="list-group-item" to="/about">About</NavLink>
<NavLink className="list-group-item" to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Switch>
<Route path='/about' component={About}/>
<Route path='/home' component={Home}/>
<Redirect to='/about'/>
</Switch>
</div>
</div>
</div>
</div>
</div>
)
}
}
pages/About.jsx
代码:
import React, {Component} from "react"
export default class About extends Component {
render() {
return <h3>这是About页面的内容</h3>
}
}
pages/Home.jsx
代码:
import React, {Component} from "react"
export default class Home extends Component {
render() {
return <h3>这是Home页面的内容</h3>
}
}
嵌套路由使用
实现效果:
pages/Home.jsx
代码:
import React, {Component} from "react"
import {NavLink, Redirect, Route, Switch} from 'react-router-dom'
import HomeNews from "./HomeNews"
import HomeMessages from "./HomeMessages"
export default class Home extends Component {
render() {
return (
<div><h2>Home组件内容</h2>
<div>
<ul className="nav nav-tabs">
<li>
<NavLink className="list-group-item" to="/home/news">News</NavLink>
</li>
<li>
<NavLink className="list-group-item" to="/home/message">Message</NavLink>
</li>
</ul>
<Switch>
<Route path='/home/news' component={HomeNews}/>
<Route path='/home/message' component={HomeMessages}/>
<Redirect to='/home/news'/>
</Switch>
</div>
</div>
)
}
}
pages/HomeNews.jsx
代码:
import React, {Component} from "react"
export default class HomeNews extends Component {
render() {
return (
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
)
}
}
pages/HomeMessages.jsx
代码:
import React, {Component} from "react"
export default class HomeMessages extends Component {
render() {
return (
<div>
<ul>
<li>
<a href="/home/message/1">message001</a>
<button>push查看</button>
<button>replace查看</button>
</li>
<li>
<a href="/home/message/3">message003</a>
<button>push查看</button>
<button>replace查看</button>
</li>
<li>
<a href="/home/message/5">message005</a>
<button>push查看</button>
<button>replace查看</button>
</li>
</ul>
<button>回退</button>
<hr/>
</div>
)
}
}
src\components\MyNavLink.jsx
内容如下:
import React, {Component} from "react"
import {NavLink} from 'react-router-dom'
export default class MyNavLink extends Component {
render() {
let props = this.props
return <NavLink className="list-group-item" {...props}></NavLink>
}
}
src\pages\Home.jsx
内容修改如下:
import React, {Component} from "react"
import {Redirect, Route, Switch} from 'react-router-dom'
import MyNavLink from '../components/MyNavLink'
import HomeNews from "./HomeNews"
import HomeMessages from "./HomeMessages"
export default 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={HomeNews}/>
<Route path='/home/message' component={HomeMessages}/>
<Redirect to='/home/news'/>
</Switch>
</div>
</div>
)
}
}
路由组件传参
- 实现效果:
src\pages\HomeMessages.jsx
内容如下:
import React, {Component} from "react"
import {Link, Route} from 'react-router-dom'
import HomeMessagesDetail from "./HomeMessagesDetail";
export default class HomeMessages extends Component {
state = {
messages: []
}
componentDidMount() {
this.setState({
messages:[
{mid:1,content:'message1'},
{mid:2,content:'message2'},
{mid:3,content:'message3'},
{mid:4,content:'message4'},
{mid:5,content:'message5'},
]
})
}
render() {
return (
<div>
<ul>
{
this.state.messages.map((item)=>{
return (
<li key={item.mid}>
<Link to={`/home/message/detail/${item.mid}`}>{item.content}</Link>
<button>push查看</button>
<button>replace查看</button>
</li>
)
})
}
</ul>
<hr/>
<Route path="/home/message/detail/:id" component={HomeMessagesDetail}/>
<hr/>
<button>回退</button>
</div>
)
}
}
src\pages\HomeMessagesDetail.jsx
内容如下:
import React, {Component} from "react"
export default class HomeMessagesDetail extends Component {
state = {
messages:[
{id:1,title:'message1',content:'这是message1的内容'},
{id:2,title:'message2',content:'这是message2的内容'},
{id:3,title:'message3',content:'这是message3的内容'},
{id:4,title:'message4',content:'这是message4的内容'},
{id:5,title:'message5',content:'这是message5的内容'},
]
}
render() {
let {id} = this.props.match.params
let {messages} = this.state
let messageTarget = messages.find((item)=>{
return item.id===parseInt(id)
})
return (
<ul>
<li>ID: {id}</li>
<li>TITLE: {messageTarget.title}</li>
<li>CONTENT: {messageTarget.content}</li>
</ul>
)
}
}
编程式路由导航
- 声明式导航
<link>
和<NavLink>
实现路由的跳转是声明式导航 -
编程式导航
通过js路由对象的方式叫做编程式导航push
replace
go
编程式导航:
类别 | 使用方法 |
---|---|
push | props.history.push('/singer') |
replace | props.history.replace({pathname:'/singer'}) |
go | props.history.go(-1) //返回 |
goback | props.history.goBack() //返回 |
goforward | props.history.goForward() //前进 |
- DEMO实现效果:
\src\pages\HomeMessages.jsx
的文件代码:
import React, {Component} from "react"
import {Link, Route} from 'react-router-dom'
import HomeMessagesDetail from "./HomeMessagesDetail";
export default class HomeMessages extends Component {
state = {
messages: []
}
componentDidMount() {
this.setState({
messages: [
{mid: 1, content: 'message1'},
{mid: 2, content: 'message2'},
{mid: 3, content: 'message3'},
{mid: 4, content: 'message4'},
{mid: 5, content: 'message5'},
]
})
}
pushShow = (path) => {
this.props.history.push(path)
}
replaceShow = (path) => {
this.props.history.replace(path)
}
goBack = () => {
this.props.history.goBack()
}
goForward = () => {
this.props.history.goForward()
}
render() {
return (
<div>
<ul>
{
this.state.messages.map((item) => {
return (
<li key={item.mid}>
<Link to={`/home/message/detail/${item.mid}`}>{item.content}</Link>
<button onClick={() => {
return this.pushShow(`/home/message/detail/${item.mid}`)
}}>push查看
</button>
<button onClick={() => {
return this.replaceShow(`/home/message/detail/${item.mid}`)
}}>replace查看</button>
</li>
)
})
}
</ul>
<hr/>
<Route path="/home/message/detail/:id" component={HomeMessagesDetail}/>
<hr/>
<button onClick={() => {
return this.goBack()
}}>回退</button>
<button onClick={() => {
return this.goForward()
}}>前进</button>
</div>
)
}
}