先了解下基础知识
路径可能的样子: http://localhost:9000/static/index/posts/edit?name=张三&age=12&gender=man#zh/en/年龄
一段完整的地址: 协议 端口 路径(/...) search(?key=value&k=v&...) hash(#...)
以前后台接收到前端的请求,不但要发送数据给前端还要返回页面
前端路由,切换页面不需要服务器返回,减少了服务器压力、单页应用
公共资源只需要请求一次即可,前端的职责就更多,前端比重就较高(逻辑多了)
安装路由:
npm i react-router-dom
history 路由:(浏览器历史记录管理)
在服务器下访问,添加浏览器历史记录的
history.pushState (数据,'浏览器都忽略的名字',你显示的 url 地址)
onpopstate
当你触发了浏览器的前进或者后退就会触发这个事件
在这个事件中,ev 下有 state 属性,可以接收到 pushState 时的数据
history.length 查看历史记录中的个数(据说最高是50个)
back() (回退)
forward() (前进)
go() ( go(-3) 后退3步 )
push() 跳转路由
this.props.history.push({ pathname: "/xxx/路径/...", params: { // 跳转后带出的信息 a: xxxx, b:xxxx } }) // 获取信息 console.log(this.props.location.params)
replace() (替换掉当前的 history 记录)
React 中如何使用路由
BrowserRouter : (浏览器路由)
1:import {BrowserRouter as Router} from 'react-router-dom';
hash路由:import {HashRouter as Router} from 'react-router-dom'; // 会有#号
2:引入把Router包在ReactDOM.render(根下);
比如:
ReactDOM.render(<Router><App /></Router>);
3:配置路由:
import {Route} from 'react-router-dom';
<Route path="/home" component={组件}/>
3.1:component={组件}也可以是一个函数( 函数声明组件)
<Route path="/home" component={(props)=>{ return <div>1234</div> // return <Ppa/> }}/>
props:
在切换路由的时候记录的细节信息,是函数的情况下,要传入路由细节。
在组件中,可以通过 this.props 去查看、使用:
match -> params、url、path (获取,params 动态路由 :id)
location -> hash、search、state (获取,hash #号后面 / search ?号后面)
history -> go() 、push()、 replace() 、 ... (改变路由,进行页面的跳转)
一般使用component的函数,都是使用函数声明组件。
注意:
component 如果放函数,一定要放有名的函数组件,
不然(匿名函数)点击多次本路由,会多次挂载和卸载
当组件拿不到 props 下,路由的相关信息时,可以使用 withRouter 去包一下
一般判断使用可选组件,使用 render={(props)=>{}}
3.2:render 可以返回 jsx 或者一个组件,更喜欢通过 render 去判断使用需求的组件。
3.3:children 跟一个函数,不管你匹不匹配path都执行组件。
4. 特性:
默认配置如果/下有组件,那么所有关于/xxx都吃得到/下的这个组件
如果,/下匹配组件,/下的xxx不想匹配/这个组件,那么可以在Route 下
加一个 exact
exact: 不写默认是 false
若果 /father 写了 exact 那么 /father/child 只会匹配到 /father ,所以建议在子路由中添加。
/one /one/two true no
/one /one/two false yes
strict: 严格匹配,默认 false
在 path 为 /detail/ 没有加 strict 那么 url 为 /detail 是能够匹配的
加了 strict 的时候,能匹配 /detail/ 或者 /detail/xxx
可以2个一起用:
<Route path="/one" exact strict component={About}/>
Link (跳转)
to=对象,带参数跳转(pathname, query, hash, state(额外数据)),注意:这些参数都被存放到 this.props.location 中
import React, { Component } from 'react'; import { Link } from 'react-router-dom'; class About extends Component { render() { console.log(this.props) return ( <div> <Link to={{ pathname: "/jump/url", hash: '#ahash', query: { foo: 'foo', boo: 'boo' }, state: { data: 'hello' } }}> </Link> </div> ); } } export default About;
Redirect (重定向)
1.引包:import { Redirect } from 'react-router-dom';
2.<Redirect to="/dashboard"/> 等同于调用了 replace() ,替换了当前的 url
to后面可以跟字符串(路径即可),
还可以跟对象(to={{pathname:'/',search:'?a=1&b=2'}})
存放数据
Switch:从上到下去读,只匹配一个
当路由既有动态路由,又有静态路由
/about/:id 动态
/about/d 静态
输入静态路由的时候,会匹配到动态路由(2个组件都会显示)
要求是:输入静态路由只显示静态。这个时候就要用 Switch
1.引包:import { Switch } from 'react-touter-dom'
2.组件:
<Switch>
/about/d
/about/:id
</Switch>
import React, { Component } from 'react'; import { Route,Link,Switch, Redirect } from 'react-router-dom'; import Home from './component/home'; import About from './component/about'; import Aboutc from './component/aboutc'; import Aboutd from './component/aboutd'; class App extends Component { render() { return ( <div> <Link to='/'><button>首页</button></Link> <Link to='/about'><button>关于</button></Link> <Route exact path='/' component={Home}/> <Route path='/about' render={(props)=>{ return <About {...props}/> }}/> <Switch> <Route path='/about/d' component={Aboutd}/> <Route path='/about/:id' component={Aboutc}/>
<Redirect from="/* to="/"> // 重定向,路径发生错误,会 to 到指定的默认路径 </Switch> </div> ); } } export default App;
(当组件拿不到 props 的时候,可以使用 withRouter 去包一下)
withRouter:
高阶组件:源于高阶函数(参数为函数,返回一个新的函数(或者一类运算结果))
function fn(f){
return f.bind(document)
}
高阶组件:传一个组件,返回另外一个组件
1.引包:import { withRouter } from 'react-router-dom'
2.导出:export default withRouter(BackHome)
import React, { Component } from 'react'; import {withRouter} from 'react-router-dom'; class BackHome extends Component { back = () => { this.props.history.push('/'); } render() { return ( <div> <button onClick={this.back}>返回首页</button> </div> ); } } export default withRouter(BackHome);
PropTypes: 能够验证父级传递进来的数据类型(为了报错)
import PropTypes from 'prop-types'; PPa.propTypes = { name: PropTypes.string //num:PropTypes.number //num:PropTypes.数据类型 } PPa.defaultProps = { // 设置默认值 name: "张三" }