React路由渲染方式与withRouter高阶组件及自定义导航组件应用详细介绍
1. 路由的三种渲染方式
1.1 component渲染方式
描述:
这种渲染方式有两种,一种是类方式渲染,一种是函数方式渲染。
语法:
<Route path="/home" component={Home} /> 或 <Route path="/home" component={(router)=><Home {…router} />} />
使用:
import React, { Component } from 'react' import { Route } from 'react-router-dom' // 匹配成功后渲染的组件 import RenderCmp from './views/Render' class App extends Component { render() { return ( <div> {/* component 类方式: 1.对于规则匹配成的组件没有办法去写逻辑,会直接渲染 2.规则匹配成功后,会给组件中的props自动映射对应的路由对象 3.当前载体中的state更新,它不会重新创建 */} <Route path="/" component={RenderCmp} /> {/* component 函数方式: 1.可以在规则匹配成功后,进行业务逻辑的判断来决定最终是否渲染 2.规则匹配成功后,它需要你把回调函数中的路由对象,手动的通过props传给要渲染的组件 3.当前的载体中的state如果,发生改变,则它对应匹配要渲染的组件会销毁并重新创建 建议: component属性的回调函数的方式,不要在工作中使用,可以用 render来代替 */} {/* <Route path="/" component={route => { if (true) { return <RenderCmp {...route} /> } return <div>没有权限</div> }} /> */} </div> ) } } export default App
1.2 render方式渲染
语法:
<Route path="/home" render={<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->router=><Home {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->…router} />} />
使用:
import React, { Component } from 'react' import { Route } from 'react-router-dom' // 匹配成功后渲染的组件 import RenderCmp from './views/Render' class App extends Component { render() { return ( <div> {/* render渲染方式 它有component类的优点也有component回调的优点,但没有component回调中的缺点 */} <Route path="/" render={route => { if (true) { return <RenderCmp {...route} /> } return <div>没有权限</div> }} /> </div> ) } } export default App
1.3 案例-登录成功才能访问某个页面
定义路由规则:
import React, { Component } from 'react' import { Redirect, Route, Switch } from 'react-router-dom' // 匹配成功后渲染的组件 import RenderCmp from './views/Render' import Login from './views/Login' class App extends Component { render() { return ( <div> <Switch> <Route path="/login" component={Login} /> <Route path="/render" render={route => { if (sessionStorage.getItem('uid')) { return <RenderCmp {...route} /> } return <Redirect to="/login" /> }} /> </Switch> </div> ) } } export default App
登录页面:
import React, { Component } from 'react' class Login extends Component { render() { return ( <div> <h3>用户登录</h3> <button onClick={() => { sessionStorage.setItem('uid', 1) this.props.history.push('/render') }} > 登录一下 </button> </div> ) } } export default Login
1.4 children方式渲染
描述:
在组件渲染显示时,不是关注与它是否显示,而是在显示的时候关注于它的路由相关信息,才用到它。
语法:
// 全匹配 <Route path="/about" children={router =>{ return <div>children渲染</div> }} /> 或 // 精确匹配 <Route path="/about" children={<About />} />
使用:
import React, { Component } from 'react' import { Redirect, Route, Switch } from 'react-router-dom' // 匹配成功后渲染的组件 import RenderCmp from './views/Render' // import Login from './views/Login' class App extends Component { render() { return ( <div> {/* children属性中传入jsx元素,则它会根据path路径来匹配规则,如果匹配成功则渲染,不会自动注入路由对象到props中 */} {/* <Route path="/sdfsf" 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 }} /> </div> ) } } export default App
2. withRouter高阶组件
描述:
作用:把不是通过路由直接渲染出来的组件,将react-router 的 history、location、match 三个对象传入props对象上
默认情况下必须是经过路由匹配渲染的组件才存在this.props,才拥有路由参数,才能使用编程式导航的写法,执行this.props.history.push(‘/uri’)跳转到对应路由的页面,然而不是所有组件都直接与路由相连的,当这些组件需要路由参数时,使用withRouter就可以给此组件传入路由参数,此时就可以使用this.props
语法:
// 引入withRouter import { withRouter} from 'react-router-dom' // 执行一下withRouter export default withRouter(Cmp)
使用:
利用 withRouter 监听路由规则变化:
import React, { Component } from 'react' // withRouter 让非路由直接匹配渲染的组件中能得在this.props中得到路由对象 import { Redirect, Route, Switch, withRouter } from 'react-router-dom' // 匹配成功后渲染的组件 // import RenderCmp from './views/Render' import Home from './views/Home' import Detail from './views/Detail' // 装饰器写法 // @withRouter class App extends Component { state = { num: 100 } componentDidMount() { // 手动让第1次执行 this.listenerRouter(this.props.location) // 监听路由变化则触发 第1次它只注册,不执行回调 this.props.history.listen(this.listenerRouter) } listenerRouter = ({ pathname }) => { console.log('listener', pathname) // 只有登录直接访问,别的都要判断是否登录 if(pathname!=='/login'){ // 判断是否登录 // if(xxx) // this.props.history.replace('/login') return; } } render() { // console.log('app', this.props) return ( <div> <Switch> <Route path="/home" component={Home} /> <Route path="/detail" component={Detail} /> </Switch> </div> ) } } // 对应装饰器写法 // export default App export default withRouter(App)
3. 自定义导航组件
App.jsx:
import React, { Component } from 'react' import Mylink from './components/Mylink' import { Route, Switch } from 'react-router-dom' import Home from './views/Home' import About from './views/About' class App extends Component { render() { return ( <div className="app"> <Mylink tag="h3" to="/home"> home页面 </Mylink> <Mylink tag="h3" to="/about"> about页面 </Mylink> <hr /> {/* 路由规则 */} <Switch> <Route path="/home" component={Home} /> <Route path="/about" component={About} /> </Switch> </div> ) } } export default App
自定义导航组件:
// Fragment 它可以当作顶层元素来包裹子元素,但它不会编译成html元素 // Fragment 有简写,简写时,可以不需要导入Fragment组件 <></> // import React, { Component, Fragment } from 'react' import React, { Component } from 'react' import { withRouter, Route } from 'react-router-dom' import types from 'prop-types' @withRouter class Mylink extends Component { jumpUrl = () => { this.props.history.push(this.props.to) } render() { let { tag: Tag, children, to, activeClassName } = this.props return ( <> <Route path={to} children={({ match }) => { // 高亮 let className = match ? activeClassName : '' return ( <Tag className={className} onClick={this.jumpUrl}> {children} </Tag> ) }} /> </> ) } } // 字段限制 Mylink.propTypes = { to: types.string.isRequired, tag: types.string, activeClassName: types.string } // 默认值 Mylink.defaultProps = { tag: 'a', activeClassName: 'active' } export default Mylink
到此这篇关于React路由渲染方式与withRouter高阶组件及自定义导航组件应用详细介绍的文章就介绍到这了,更多相关React路由渲染方式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
React Native全面屏状态栏和底部导航栏适配教程详细讲解
最近在写 React Native 项目,调试应用时发现顶部状态栏和底部全面屏手势指示条区域不是透明的,看起来很难受。研究了一下这个问题,现在总结一下解决方案,这篇文章主要介绍了React Native全面屏状态栏和底部导航栏适配教程2023-01-01详解React Native 采用Fetch方式发送跨域POST请求
这篇文章主要介绍了详解React Native 采用Fetch方式发送跨域POST请求,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2017-11-11使用react-activation实现keepAlive支持返回传参
本文主要介绍了使用react-activation实现keepAlive支持返回传参,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2022-05-05
最新评论