react ——withRouter——页面隐式传值—嵌套路由——渲染方式——自定义导航组件
withRouter
import {Route,Switch,withRouter} from "react-router-dom"
withRouter高阶组件增强组件——获取路由对象。
withRouter 让非路由直接匹配渲染的组件中能得在this.props中得到路由对象
@withRouter
class App extends Component {
render() {
console.log(this.props);
******
}
}
export default withRouter(App);
通过state隐式来传递数据到目标页面
声明式:
import {Route,Switch,withRouter} from "react-router-dom"
<NavLink to={{pathname:'/home', state:{name:"detail过来的数据"}}}>点击切换到home</NavLink>
编程式
onClickHandler = ()=>{
this.props.history.push({
pathname:"/home",
state:"detail",
search:"name:userzhang"
});
}
嵌套路由
- 在子路由定义的组件中,可以通过props中提供的路由对象来获取父路由定义的地址
- 在定义嵌套路由时,父路由一定一定一定不能定义为严格模式
<div>
<h3>后台首页</h3>
<NavLink to={{pathname:"/admin/index"}}>[index]</NavLink>----
<NavLink to={{pathname:"/admin/user"}}>[user]</NavLink>
<hr />
<Switch>
<Route path="/admin/index" component={Index}></Route>
<Route path="/admin/user" component={User}></Route>\
<Route component={User}></Route>{/* 子路由一个都没匹配上渲染此路由组件 */}
</Switch>
</div>
通过渲染类和通过函数渲染的区别
类:<Route path="/" component={RenderCmp} />t
1.对于规则匹配成的组件没有办法去写逻辑,会直接渲染
2.规则匹配成功后,会给组件中的props自动映射对应的路由对象
3.当前载体中的state更新,它不会重新创建
函数:<Route path="/" component={回调函数返回一个组件} />
1.可以在规则匹配成功后,进行业务逻辑的判断来决定最终是否渲染
2.规则匹配成功后,它需要你把回调函数中路由对象,手动的通过props传给要渲染的组件
3.当前的载体中的state如果,发生改变,则它对应匹配要渲染的组件会销毁并重新创建
建议: component属性的回调函数的方式,不要在工作中使用,可以用 render来代替
render渲染方式<Route path="/" render={route => {} />
它有component类的优点也有component回调的优点,但没有component回调中的缺点
4、children渲染方式
children属性中传入jsx元素,则它会根据path路径来匹配规则,如果匹配成功则渲染,不会自动注入路由对象到props中
<Route path="/home" children={<RenderCmp />} />
- children属性为一个函数,则它的渲染不会根据路由规则来匹配渲染,它默认都会渲染出来
- 在此函数的形参中有一个路由对象,此对象中有一个match属性,如果当前访问的地址和path路径一致,则返回为对象,否则为null
- 函数方式: 如果你当前的页面中有一些显示的元素它在任何的地址中都要显示,且还要根据是否是激活路由,而高亮出来,就可以用它
<Route
path="/home"
children={route => {
// console.log('match', route.match)
// return <RenderCmp {...route} />
return route.match ? <RenderCmp {...route} /> : null
}}
/>
登录验证
受控表单,点击后数据存储在本地缓存,跳转路由
state = {
username:{
value:"",
onChange:e=>this.setState(state=>({username:{...state.username,value:e.target.value.trim()}}))
}
}
onClickHandler = ()=>{
localStorage.setItem("username",this.state.username.value);/* 点击后存储跳转到后台 */
this.props.history.push("/admin")
}
完成一次渲染时候的判断:
<Route
path='/admin'
render={(route)=>{
if(localStorage.getItem("username")){
return <Admin/>
}else{
return <Redirect to="/login"/>
}
}}
></Route>
自定义导航组件
取消顶级元素的包裹,降低dom操作的深度和标签繁杂嵌套
Fragment 它可以当作顶层元素来包裹子元素,但它不会编译成html元素
Fragment 有简写,简写时,可以不需要导入Fragment组件 <></>
import React, { Component, Fragment } from 'react'
<Fragment>
<h1>text_render</h1>
</Fragment>
===================
<>
<h1>text_render</h1>
</>
根据传给组件的props,生成对应的导航组件,组件身上传过去的值来访问请求组合成一个自定义的组件。
<div>
<h1>Mylink</h1>
<Mylink tag="h3" to="/render/home">home页面</Mylink>
<Mylink tag="h3" to="/render/about">about页面</Mylink>
<hr />
<Switch>
<Route path="/render/home" component={Home}></Route>
<Route path="/render/about" component={About}></Route>
</Switch>
</div>
Mylink组件关键代码
onClickHandler = (to)=>(e)=>{
this.props.history.push(to);
}
render() {
let {tag:Tag,to,children} = this.props
return (
<>
<Tag onClick={this.onClickHandler(to)}>{children}</Tag>
</>
);
}