ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# react-router ## Router 核心在于实现URL与path相同时的组件渲染。使用matchPath方法进行检测。 ~~~ const matchPath = (pathname, options) => { const { exact = false, path } = options if (!path) { return { path: null, url: pathname, isExact: true, } } const match = new RegExp(`^${path}`).exec(pathname) if (!match) { // There wasn't a match. return null } const url = match[0] const isExact = pathname === url if (exact && !isExact) { // There was a match, but it wasn't // an exact match as specified by // the exact prop. return null } return { path, url, isExact, } } ~~~ > 首先进行空检测,当发现 path 为未定义或者为空时则直接返回匹配成功(组件不指定path则默认渲染)。接下来使用正则检测传入的 path 与当前的 location.pathname 是否匹配,不匹配则返回 null。如果匹配成功还要检测下是否是完全匹配,即全等。如果不是完全匹配,却传入了 exact 为 true 的选项,匹配依然失败返回null,其余情况匹配成功。 最后,如果传入了一个组件或者render函数,则分别调用 React.createElement 及 render 函数将其渲染,并传入 props。实际情况传入的 props 有很多,这里做了简化。 ## Link ~~~ <Link to='/some-path' replace={false} /> ~~~ to 是一个指向跳转目标地址的字符串,而 replace 则是布尔变量来指定当用户点击跳转时是替换 history 栈中的记录还是插入新的记录。Link 组件的渲染函数中需要返回一个锚标签,不过我们的前提是要避免每次用户切换路由的时候都进行整页的刷新,因此我们需要为每个锚标签添加一个点击事件的处理器:我们要禁止 a 标签的跳转行为。在使用 browserHistory 的情况下此时我们本质上会使用 HTML5 中的 pushState 与 replaceState 函数,这里进行了简单包装。 ## 渲染 最后,我们需要考虑如何保证用户点击了 Link 组件之后触发全部路由组件的检测与重渲染。在我们上面实现的 Link 组件中,用户执行跳转之后浏览器的显示地址会发生变化,但是页面尚不能重新渲染;我们声明的 Route 组件并不能收到相应的通知。我们需要追踪那些显现在界面上实际被渲染的 Route 组件并且当路由变化时调用它们的 forceUpdate 方法。 Router 主要通过有机组合 setState、context 以及 history.listen 方法来实现该功能。每个 Route 组件被挂载时我们会将其加入到一个数组中,然后当 path 变化时,我们可以遍历该数组然后对每个实例调用 forceUpdate 方法: