react-router-dom v6
基于 React 编写的 React 前端路由库。
BrowserRouter
调用 createBrowserHistory 创建了一个 history 对象,访问 history.action、history.location 属性,将 location、action 作为 props 传递给 Router 组件渲染对应路由。同时通过 history.listen 监听 history 对象的改变,一旦发生改变,就通过 setState 修改 loaction 和 action 的值。从而导致 children 重新渲染。
HashRouter
调用 createHashHistory 创建了一个 history 对象,然后流程和 BrowserRouter 一样。
Link
渲染一个 a 标签,通过 useHref 获取到完整路径,通过 useLinkClickHandler 返回的函数进行路由跳转同时会阻止浏览器默认行为。
如果对在 Link 的 onClick 事件的函数中执行了 event.preventDefault(),点击 Link 后,路由将不会改变。
如果 Link 的 reloadDocument 为 ture,点击则会刷新页面。Link 内部 useLinkClickHandler 返回的函数依旧不会执行。路由能够跳转是因为重新向服务器请求了对应 url 的资源。
react-router
Router
通过 basename 和 pathname 来判断顶级路由是否匹配,来决定是否渲染 children。
匹配后使用 NavigationContext 和 LocationContext 来向下传递状态,让需要的组件自己订阅对应的状态。
Routes
使用 createRoutesFromChildren 根据 Routes 组件的 children 创建一个 route 配置对象数组。然后再把配置对象数组传入 useRoutes 经过路由匹配和排序后返回一个 React.ReactElement 元素。
matches.reduceRight((outlet, match, index) => {
return (
<RouteContext.Provider
children={
match.route.element !== undefined ? match.route.element : outlet
}
value={{
outlet,
matches: parentMatches.concat(matches.slice(0, index + 1)),
}}
/>
);
}, null as React.ReactElement | null);
//上面的代码形成一个匹配路由的嵌套树。在我们编写的组件中使用 <Outlet/> 时,就是通过 useContext 访问了上面代码中对应嵌套层次的 outlet,才能在父路由组件中渲染子路由组件。
Route
该组件的目的只是为了声明路由和对应的组件。
该组件必须被包裹在 Routes 组件内部,不能直接渲染,否则会抛出异常。因为该组件内部只有一段抛出异常的代码,避免没有被 Routes 包裹直接渲染。
history v5
使用 JavaScript 来管理会话和历史记录,同时屏蔽了不同平台和不同的路由模式的差异。
createHashHistory
通过执行 createHashHistory(),创建了一个 hashHistory 对象,提供了 push、replace、listen等方法,通过 listen 方法可以添加订阅函数。
监听路由变化
1、通过监听
hashchange、popstate事件,在事件回调函数中执行通过listen方法添加的订阅函数。将路由跳转后的action和location作为参数传递到订阅函数中。2、提供
push、replace等方法,在push、replace内部通过history.pushState(方法执行失败时会通过 window.location.assign(url) 修改 url)和history.repalceState方法修改 url。然后执行通过listen方法添加的订阅函数,将路由跳转后的action和location作为参数传递到订阅函数中。
注意
当通过 window.location.hash 修改 url 的 hash 时,会触发 popstate 和 hashchange 事件,先触发 popstate 事件,再触发 hashchange 事件(在该事件回调函数中会判断 url 是否相等,避免重复执行)。
createBrowserHistory
通过执行 createBrowserHistory(),创建了一个 browserHistory 对象,提供了 push、replace、listen等方法,通过 listen 方法可以添加订阅函数。
监听路由变化
1、通过监听
popstate事件,在事件回调函数中执行通过listen方法添加的订阅函数。将路由跳转后的action和location作为参数传递到订阅函数中。2、提供
push、replace等方法,在push、replace内部通过history.pushState(方法执行失败时会通过 window.location.assign(url) 修改 url)和history.repalceState方法修改 url。然后执行通过listen方法添加的订阅函数,将路由跳转后的action和location作为参数传递到订阅函数中。