ZF_react react-router 使用正则匹配路由,Switch路由,嵌套路由的实现 路由保护 NavLink withRouter

正则匹配路由

在这里插入图片描述
这样的设计不太合理。
path-to-regexp
使用这个库可以将路劲转化为正则。
在这里插入图片描述
在这里插入图片描述
可以通过第二个参数keys获取到params的数组,然后抽离出来。再利用match匹配到的数组,去取出对应的数据。如
在这里插入图片描述
z最后拿到的对象就是我们要的。

match对象的实现

Route对象有三个Porps,history,match,location。我们已经实现了location,history。现在实现match
在这里插入图片描述
通过这个函数拿到Match。
在这里插入图片描述
借助刚才那个path-to-regexp的库,将Route的path, 根据Route传入的属性,比如exact,strict, sensitive转化成对应的正则,然后去匹配。然后再判断是否相等。
效果:
在这里插入图片描述
没有加exact
在这里插入图片描述
加了exact
在这里插入图片描述
就能精准的匹配到。在这里插入图片描述

Switch的实现

在这里插入图片描述
在这里插入图片描述
如果我们有两个路由是一样的,那么就会渲染两个,使用Switch组件就可以实现精准的渲染第一个。
实现思路:拦截Swtich的children,一个一个遍历,如果匹配到了就退出循环,不再执行下一个Route。
在这里插入图片描述
在这里插入图片描述
如图,一旦macth匹配到了,就证明有值了。
在这里插入图片描述
效果:
在这里插入图片描述
只渲染一个了。

实现Link

link是一个a标签,但是a
我们要拦截他然后使用自己的Push方法,因为to可能接受的是对象。在这里插入图片描述
做一个兼容处理。在这里插入图片描述
在这里插入图片描述
成功实现。

嵌套路由

嵌套路由只需要在这里插入图片描述
从父亲开始依次写Route即可,记住,Route的位置就是component的渲染位置,而且在这里插入图片描述
有子组件的Route,不要加exact属性,因为只会匹配到Home就结束了,不会匹配到里面的Route。Route位置不能乱写,比如User的自组建的Route不能写到Home里面去,因为路由匹配是从最外层的Route匹配进去的,如果路劲为/user/list,则Route的path为user的组件渲染,然后再渲染里面的。而Home组件会因为第一层path匹配不过关而返回null,里面的vdom不再渲染。
在这里插入图片描述
在这里插入图片描述
这里如果用的是hash,刷新就会报错,因为hash刷新不会纪律当前的状态state,而换成browserRouter刷新就不会报错,因为history刷新的时候会纪录state。

实现受保护的路由

有的组件没有权限无法就无法观看,所以我们必须做权限控制。如
在这里插入图片描述
使用高阶组件在外层做一层权限判断。
Route中渲染组件内容的有三种方法:
1 component属性
2 render属性
3 children属性
在这里插入图片描述
实现render属性
在这里插入图片描述

实现Redirect

在这里插入图片描述
点击user
在这里插入图片描述
会自动跳到Login页面。

实现NavLink

可以在link匹配的时候加上类名和样式
在这里插入图片描述

在这里插入图片描述

NavLink会在匹配的时候合并activeClassName与className,并且合并style。
实现:
通过我们实现的matchPath来判断当前是否匹配,如果匹配就合并类名和style。在这里插入图片描述

效果一样:
在这里插入图片描述

WithRouter的实现在这里插入图片描述

在这里插入图片描述
这个Props没有history,咩有loaction,没有match。因为他不是Route组件。我们的props只在Route组件中处理,让Route渲染的组件带有三个属性。而普通组件是没有的。所以withRouter可以实现在普通组件中也能拿到这三个属性。
实现思路:
withRouter是个高阶组件,通过context获取三个属性,再传给子组件即可。
在这里插入图片描述
在这里插入图片描述
如上,直接通过context.Consumer就可以获取三个属性并传入进去。这里为什么不能返回RouterContext.Consumer,而是要通过先返回一个函数组件。传props是一点,其次是直接返回RouterContext.COnsumer,因为我们这个withRouter是要执行一次的,不是直接作为组件<WithRouter/ >这样去使用的,执行一次后,如果返回的是一个<RouterContext.COnsumer /> ,babel会将其转化为vdom也就是一个对象,如果一个对象去作为组件,此时Babel再转化的时候,react元素type的值就是这个vdom,而type的值是不可以是对象的,所以报错了。
如:
在这里插入图片描述
在这里插入图片描述
直接作为组件,没问题。在这里插入图片描述
在这里插入图片描述
作为组件,他没还执行,此时是一个函数,会被babel转化u为正常的vdom。而执行过一次后,他的值就是一个vdom。此时再将它作为组件,就会报错。如
在这里插入图片描述
在这里插入图片描述
当B再作为组件的时候,会将上面打印的vdom作为createElement的type值传进去,就会报错。
所以只能返回一个函数。在这里插入图片描述
在这里插入图片描述
即使执行一次,B依然是一个函数组件,还没转化过。所以可以作为组件使用。

Guess you like

Origin blog.csdn.net/lin_fightin/article/details/121051504