发布网友 发布时间:2024-10-05 01:31
共1个回答
热心网友 时间:2024-10-05 08:28
简介React-Router6出来有一段时间了,笔者感觉v6版的路由比v4/v5更好用了,不知道你们有没有这样的感觉,特别是在路由嵌套和通过配置文件渲染路由这一块,简直不要太爽。
今天我们对比React-Router4/5来总结下React-Router6新特性,希望能让小伙伴们快速上手。
<Switch/>替换为<Routes/>React-Router6版本移除了<Switch/>组件,并使用<Routes/>替换。
除了能替代<Switch/>组件的功能外,也做了一些改变,比如所有的<Route>都必须包裹在<Routes/>中,否则抛出错误。
React-Router4/5使用Switch<Switch><Routepath="/home"component={Home}/><Routepath="/login"component={Login}/></Switch>React-Router6使用Routes<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes><Route/>用法变化React-Router6版本<Route/>组件变化较大,移除了component与render属性,使用element属性替代,因此与之前的版本代码写法不兼容。
React-Router4/5使用component收组件<Routepath="/home"component={Home}/><Routepath="/login"render={()=><Login/>}/>React-Router6使用element接收组件<Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/>重定向React-Router6移除了<Redirect/>组件,但可以使用新增的<Navigate/>组件配合<Route/>组件实现重定向效果。
React-Router4/5使用Redirect在React-Router4/5中使用<Redirect/>组件。
<Routepath='/user'}>{/*支持绝对路径和相对路径*/}<Redirectto="/user/info"/>{/*<Redirectto="info"/>*/}</Route>React-Router6使用NavigateReact-Router6需要<Navigate/>组件配合<Route/>组件实现重定向效果。
不清楚<Navigate/>组件的不要紧,笔者后面会细说。
{/*支持绝对路径和相对路径*/}<Routepath="/user"element={<Navigateto="/user/info"/>}><Routepath="/user"element={<Navigateto="../info"/>}>路由跳转在React-Router4/5中,我们的路由组件props会自动注入history、location、match三个路由相关属性,用来操作路由。
history用来进行路由跳转,location用来进行参数获取,match用来获取params参数。
并且不是路由组件想要使用路由属性也是可以的,类组件可以通过withRouter高阶组件包裹来实现,函数组件可以使用withRouter高阶组件包裹和useHistory、useRouteMatch、useParams三个hook来实现。
但是在React-Router6中,路由组件props不再自动注入history、location、match三个路由相关属性。并且移除了withRouter高阶组件。
React-Router4/5使用history、Link、NavLinkReact-Router4/5可以使用history或者Link、NavLink来实现路由跳转。
//Link字符串形式<Linkto="/courses"/>//Link对象形式<Linkto={{pathname:"/courses"}}/>//函数组件history形式props.history.push("/courses")props.history.replace("/courses")//函数组件historyhook形式consthistory=useHistory("/courses")history.push("/courses")history.replace("/courses")//类组件history形式this.props.history.push("/courses")this.props.history.replace("/courses")React-Router6使用navigate、Link、NavLink因为React-Router6中,路由组件props不再自动注入history所以我们不能再使用以前的方法来进行路由跳转了。
React-Router6新增了navigate用来代替history来进行路由的跳转,但是因为是hook的原因,所以只能用在函数组件中。
那类组件应该怎么办呢?我们可以看看官方的解释。官方也是推荐我们自己来封装withRouter高阶组件,以便类组件能使用路由。
import{useLocation,useNavigate,useParams}from"react-router";//https://github.com/remix-run/react-router/issues/7256exportdefaultfunctionwithRouter(Child){return(props)=>{constlocation=useLocation();constnavigate=useNavigate();constparams=useParams()return(<Child{...props}navigate={navigate}location={location}params={params}/>);};}我们用自己封装的withRouter高阶组件包裹我们的类组件就能在类组件props中获取到navigate、location、params对象啦。
后面的例子,笔者假设类组件都使用withRouter包裹了。
React-Router6使用navigate或者Link、NavLink来实现路由跳转。
//Link字符串形式<Linkto="/courses">courses</Link>//Link对象<Linkto={{pathname:"/courses"}}>courses</Link>//通过自定义withRouter类组件通过this.props.navigate实现跳转。//函数组件通过props.navigate或useNavigate实现跳转。//navigate相对路径形式navigate("../route3/75");//navigate绝对路径形式navigate("/router/route3/75");//navigate对象形式navigate({pathname:"/courses"});路由参数传递和参数获取前面已经说了React-Router6中,路由组件props不再自动注入history、location、match三个路由相关属性。所以获取参数的方式也发生了改变。
React-Router4/5路由参数传递React-Router4/5支持params、search、state三种参数。
//Link字符串形式<Linkto="/courses?sort=name"/>//Link对象形式<Linkto={{pathname:"/courses",search:"?sort=name",hash:"#the-hash",state:{fromDashboard:true}}}/>//以类组件为例字符串形式this.props.history.push("/courses?sort=name")//以类组件为例对象形式this.props.history.push({pathname:"/courses",search:"?sort=name",hash:"#the-hash",state:{fromDashboard:true}})React-Router4/5路由获取参数params需要我们配置动态路由,然后在路由的match.params或者在函数组件中使用useParams获取。
search笔者感觉非常不友好,没有vue-router中的query好用。如果要使用需要使用URLSearchParams封装。
state传递参数需要注意的一点是当使用HashRouter的时候,页面刷新state参数会丢失。
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>0React-Router6路由传递参数React-Router6使用navigate来进行路由的跳转和传参。
前面已经说了React-Router6路由组件props不再自动注入history。
在类组件需要我们单独封装withRouter组件才能在类组价获取navigate。
在函数组件我们使用useNavigate获取navigate。
React-Router6传参需要注意两个点:
传递state不再是对象里面传递了,而是单独传递,这是和React-Router4/5的区别。
navigate跳转路径支持相对路径模式,类似我们终端操作。
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>1React-Router6路由获取参数params需要我们配置动态路由,在类组价我们可以使用自己封装的withRouter高阶组件通过params获取。在函数组件中使用useParams获取。
search在类组价我们可以使用自己封装的withRouter高阶组件通过location获取。在函数组件可以使用useSearchParams或useLocation获取。
state在类组价我们可以使用自己封装的withRouter高阶组件通过location获取。在函数组件可以使用useLocation获取。需要注意当使用HashRouter的时候,页面刷新state参数会丢失。
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>2路由嵌套使用过vue-router的同学是不是感觉react-router的路由嵌套非常难用,至少笔者有这样的感觉。
但是React-Router6版本对路由嵌套这块的改动是比较大的。改版后和vue-router的使用很像。
React-Router4/5父子都需要定义路由在React-Router4/5中,子路由配置需要写到对应的子页面,让业务代码和路由逻辑混杂在一起,非常不友好。并且子路由需要补全父路由路径,哇崩溃。
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>3React-Router6支持根组件统一定义路由他来啦,他来啦。在React-Router6中,子路由配置不强制写到对应的子页面,有新的使用方式,非常友好。并且子路由也无需补全父路由路径。是不是爽到爆。
笔者的感觉就是跟vue-router靠齐了。
在React-Router6中,以前的嵌套写法还是没有移除,只是做了些许改动。
需要注意的有两点:
/user/*,也就是需要在父组件路由下带上*,表示这是一个父路由。
子路由不再需要补充父路由路径,比如下面的info、detail,会自动生成/user/info、/user/detail。
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>4React-Router6全新写法。
子路由不再需要写到子路由页面,全部在外面配置。只需要写上<Outlet/>即可,子路由匹配上到时会渲染在这里。类似vue里面的router-view。
子路由不再需要补充父路由路径,比如下面的info、detail,会自动生成/user/info、/user/detail。
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>5当然子路由写全路径也是支持的,但是没必要。
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>6通过配置渲染路由在React-Router4/5中,如果想实现类似vue中的routes通过配置来渲染路由是很麻烦的。但在React-Router6使用useRoutes方法可以很方便的实现。
React-Router4/5使用map或react-router-config首先我们需要定义routes
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>7在根组件,我们需要自己使用map遍历渲染,并把子路由通过routes传递下去。
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>8在子组件我们还需要继续使用map遍历渲染。
<Routes><Routepath="/home"element={<Home/>}/><Routepath="/login"element={<Login/>}/></Routes>9是不是很复杂,但是我们可以使用react-router-config插件进行简化。
首先安装react-router-config
<Routepath="/home"component={Home}/><Routepath="/login"render={()=><Login/>}/>0在根组件,我们只需要使用renderRoutes方法就可以了。
<Routepath="/home"component={Home}/><Routepath="/login"render={()=><Login/>}/>1在子组件我们继续使用renderRoutes。
<Routepath="/home"component={Home}/><Routepath="/login"render={()=><Login/>}/>2相对自己写遍历是不是方便了很多呢?其实react-router-config插件内部实现跟笔者上面写的差不多。
React-Router6使用useRoutes在React-Router6能更方便的实现。只需要使用useRoutes方法。
首先定义routes
<Routepath="/home"component={Home}/><Routepath="/login"render={()=><Login/>}/>3在根组件,我们只需要使用useRoutes方法就可以了。
这里需要注意useRoutes是hook,所以只能在函数组件或自定义组件使用。
<Routepath="/home"component={Home}/><Routepath="/login"render={()=><Login/>}/>4在子组件我们继续使用Outlet渲染子组件就可以了。
<Routepath="/home"component={Home}/><Routepath="/login"render={()=><Login/>}/>5是不是很简单,感觉React路由这一块有点向Vue-Router靠齐了,从路由嵌套和配置式路由就能看出来,后面把路由钩子也更新出来就更爽啦。
后记感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!
原文:https://juejin.cn/post/7103731196856631327