react-router

4
open
sqshada
sqshada
Posted 1 month ago

react-router #19

react-router-dom 、react-router 和 history 库三者什么关系

  • historyreact-router 核心,里面集成了 popStatepushState 等路由现实方法。
  • react-router 封装了 RouterRouteSwitch 等组件,实现了路由的改变到组件的更新。
  • react-router-domreact-router 的基础上添加了 LinkBrowserRouterHashRouter 组件。

单页面实现核心原理

原理:切换 url,监听 url 的变化,从而渲染不同的页面组件

history 模式

改变路由:history.pushState、history.replaceState

监听路由:history.popState

注意⚠️:用 history.pushState() 或者 history.replaceState() 不会触发 popState 事件。 popState 事件只会在浏览器某些行为下触发, 比如点击后退、前进按钮或者调用 history.back()、history.forward()、history.go()方法。

hash 模式

改变路由:window.location.hash 监听路由:onhashchange

Router Hooks

  • useHistory:直接访问 history 不再通过 props
  • useParams:直接访问到路由参数
  • useLocation:直接返回当前 URL 的 location 对象
sqshada
sqshada
Created 3 weeks ago

listen

history 使用观察者模式,来进行 location 的监听。任何时候 location 改变,history 对象都会调用所有的监听函数。location 改变后会触发 context (React context)进行更新,消费 context 的组件都会重新渲染,当前 Route 会重新渲染,通过对当前 location 的 pathname 进行匹配

sqshada
sqshada
Created 3 weeks ago

BrowserRouter

import { createBrowserHistory as createHistory } from "history";
class BrowserRouter extends React.Component {
  history = createHistory(this.props) 
  render() {
    return <Router history={this.history} children={this.props.children} />;
  }
}

通过 createBrowserHistory 创建 history 对象传递给 Router 组件

sqshada
sqshada
Created 3 weeks ago

createHashHistory

import { createHashHistory as createHistory } from "history";

/**
 * The public API for a <Router> that uses window.location.hash.
 */
class HashRouter extends React.Component {
  history = createHistory(this.props);

  render() {
    return <Router history={this.history} children={this.props.children} />;
  }
}

通过 createHashHistory 创建 history 对象传递给 Router 组件

sqshada
sqshada
Created 3 weeks ago

Router 是整个应用路由的传递者和派发更新者。

BrowserRouter 或者 HashRouter,两者关系就是 Router 作为一个传递路由和更新路由的容器,而 BrowserRouter 或 HashRouter 是不同模式下向容器 Router 中注入不同的 history 对象。

  • React-Router 通过 context 上下文方式传递的路由信息,context 改变,使消费 context 组件更新。
  • props.history 通过 BrowserRouter 或 HashRouter 创建 history 对象,当路由改变,会触发 listen 方法,传递生成新的 location 对象,通过 setState 改变 context 中的 value,所以路由的改变本质上是 location 改变带来的作用。

Route

Route 核心就是:匹配路由、路由匹配、渲染组件。

四种 Route 编写格式

<Switch>
  <Route path='/router/component'   component={RouteComponent}   /> { /* Route Component形式 */ }
  <Route path='/router/render'  render={(props)=> <RouterRender { ...props }  /> }  {...mes}  /> { /* Render形式 */ }
  <Route path='/router/children'  > { /* chilren形式 */ }
      <RouterChildren  {...mes} />
  </Route>
  <Route path="/router/renderProps"  >
      { (props)=> <RouterRenderProps {...props} {...mes}  /> }  {/* renderProps形式 */}
  </Route>
</Switch>

嵌套路由

嵌套路由子路由一定要跟随父路由。

比如父路由是 /home,子路由形式就是 /home/XXX,否则路由页面将不能展示

/* 第二层嵌套路由 */
function Home(){
    return <div>
        <Route path='/home/test' component={Test}   />
        <Route path='/home/test1' component={Test1}  />
    </div>
}

/* 第一层父级路由 */
function Index(){
    return <Switch>
        <Route path="/home" component={Home}  />
        <Route path="/list" component={List}  />
        <Route path="/my" component={My}  />
    </Switch>
}