react-router
基本使用(配合react-redux用路由守卫写一个登录)
点击用户中心若登陆正常显示,若未登录跳转登录页,登录页登录成功后跳转回原页面。若直接url到登录页,登陆成功后默认跳转回首页。
store.js & index.js
App.js
PrivateRoute
Login
User
BrowserRouter
使⽤HTML5提供的history API(pushState , replaceState 和 popstate 事件)
HashRouter
HashRouter 使⽤URL的hash值(即window.location.hash)
官方提示注意:hash history 不⽀持 location.key 和location.state。在以前的版本中,我们曾尝试 shim这种⾏为,但是仍有⼀些边缘问题⽆法解决。因此任何依赖此⾏为的代码或插件都将⽆法正常使⽤。由于该技术仅⽤于⽀持旧浏览器,因此我们⿎励⼤家使⽤BrowserHistory。
BrowserRouter 和 HashRouter区别
-
HashRouter简单,不需要服务器端渲染,靠浏览器的#来区分路径即可,BrowserRouter需要服务器端对不同的URL返回不同的HTML,后端配置可参考。如果服务器是nginx其实就是配置try_files
-
BrowserRouter使⽤HTML5 history API , HashRouter 使用URL的hash值
-
HashRouter不⽀持location.key和location.state,动态路由跳转需要通过?传递参数。
-
官方提示:Hash history 不需要服务器任何配置就可以运⾏,如果你刚刚⼊⻔,那就使⽤它吧。但是我们不推荐在实际线上环境中⽤到它,因为每⼀个web 应⽤都应该渴望使⽤browserHistory。
实现
App.js 首先实现BrowserRouter Link Route
BrowserRouter
BrowserRouter很简单就是显示插槽中的组件内容。
Link
- Link首先能接收to和children,接着返回一个a标签。
Route
Route首先能接收path和component,根据路径比对渲染对应的页面。
现在基本实现点击切换路由显示对应页面,但是切换的时候存在闪烁的现象,这就是a标签的原生态了。进一步修改Link。
此时点击切换不会再闪烁 但是点击事件也被禁止了。我们需要引入history让编程式导航去推动。history从哪来,在BrowserRouter通过context注入进来。
首先创建context/react-router-context
修改BrowserRouter.js使用context把创建的history注入
修改Link.js接收到history使用history.push完成编程式导航
此时点击切换路径无问题而页面还未跟着切换渲染,想法是Provider value值发生变动当前的组件是会被重新渲染的,所以可以监听location的变化达到组件重新渲染的目的。
- 修改BrowserRouter.js 使用history.listen监听location改变触发setState,使用context把创建的loaction注入
修改Route.js接收context
修改BrowserRouter.js 组件卸载时销毁监听
实现component children render三大渲染形式
对于component通过简单的React.createElement(component,props)搞定了
修改下App.js
修改Route.js
首先要知道路由渲染后的组件的this.props有啥有history 有location 有match:
所以在创建组件时需要把这些传下去。
紧接着就是三元逻辑判断:
match 匹配成功渲染children, component, render 或者 null
match 匹配成功渲染children两种情况 1.children为function 2.children本身也就是节点
match 匹配不成功渲染children 或者 null
children和location无关所以children和匹配无关 不管有没有匹配都会渲染
此时动态路由与嵌套路由也能正常执行
由于嵌套最里层的肯定要匹配最近一层的,也就是下一级肯定是拿到上一级传递的props而不是一开始注入的props 修改Route.js
Switch
App.js
Switch.js
对于Switch还可以传loaction参数(无论切换任何路由都只显示location设置的路由)
App.js
Switch.js
对于404 没有path现在返回的上下文是BrowserRouter的match 而BrowserRouter没有传match 所以match为undefined,最终返回了null而没有显示404页面。所以在BrowserRouter初始化一个match
修改BrowserRouter.js
此时match就不是undefined了执行React.cloneElement(element, {location})
到了Route.js
修改Switch.js
修改Route.js
Redirect(这里就用之前写的路由守卫做测试了)
App.js
PrivateRoute
Redirect.js