乐趣区

关于react.js:手撸Router还要啥Router框架让reactroutervuerouter躺一边凉快去

有没有发现,在大家应用 React/Vue 的时候,总离不开一个小尾巴,到哪都得带着他,那就是 react-router/vue-router,而基于它们的第三方框架又呈现很多个性化约定和扩大,比方 nuxtjs/nextjs/umijs 都纷纷推出本人的路由计划。

有没有想过,其实你能够齐全解脱他们都解放?而且并不简单,上面听我来剖析剖析:

State 能够管制所有 UI

首先 React/Vue 都是基于 MVVM 架构,State 能够决定 Component 的显示与否,而且很简略:

// jsx
{show? <SubUI /> : null}

// vue
<SubUI v-if="show" />

也能够依据 State 来动态显示组件:

<component :is="componentA"></component>

管制 UI 的办法有很多,我就不例举了,总之 State 才是掌控 UI 的大脑中枢。

将 URL 映射为 State

路由的作用,无非就是依据 Url 来管制 UI 展现,那么你只须要将 Url 映射成为 State,不就达到目标了?

Url 次要分 2 局部,pathnamequery,有很多第三方库提供解析它们的办法,比方:

  • pathname 解析:path-to-regexp:

    const regexp = pathToRegexp("/:foo/:bar");
    regexp.exec("/test/route");

    具体用法大家看看官网文档就能够了,很简略 …

  • query 解析:query 其实很灵便,没有规定非得用什么格局,最简略的你间接用 JSON.stringify 将序列化后的字符串作为 query 也能够,如果你想遵循罕用的格局,你能够应用:query-string 或者 qs

    queryString.parse(location.search)

    好了,当初你能够拿到解析 Url 后的数据,而后把它们转换成你想要的 State,寄存在全局 Store 中就能够了,比方你定义一个 Url:

/member/list/3?uname=lily

// 提取路由信息
getRouteParams(): RouteParams {const query = queryString.parse(location.search);
    const [, curModule='', curView='', id=''] = pathToRegexp('/:curModule/:curView/:id')
    .exec(location.pathname) || [];
    if (curView === 'list') {
       // 如果是列表,ID 示意以后页码
       return {...query, pageCurrent: id, curView}
    } else if(curView === 'detail') {return {...query, id, curView}
    }
}

而后在 UI 中拿到这几个 State(可通过 Redux 或 Vuex):

const Component = ({curView}) => {
  return (
    <>
      {curView === 'list' && <List />}
      {curView === 'detail' &&  <Detail />}
    </>
  );
};

发动路由跳转

基于 pushStatereplaceState,封装一下就能够了:

window.history.pushState(null, '', url);
window.history.replaceState(null, '', url);
const Link = ({url, action, ...props}) => {const onClick = (event: MouseEvent) => {event.preventDefault();
    window.history[`${action}State`](null, '', url);
  }
  return <a onClick={onClick} {...props} />;
}

监听路由变动

监听 popstate 事件就行了:

window.addEventListener('popstate',() => {
  // 解析 Url 并更新 Store
  //...
});

手撸的益处

  • UI 渲染更纯正,将 UI 的生杀大权牢牢把握在 State 手中,UI = render(state),路由和其它因子都被挡在外围,当作一种影响 State 的副作用之一。
  • 灵活性更高,你能够把 URL 映射成为任何 State,从而管制任何 State 能管制的货色,比方用 Url 来管制一个按钮的启用与禁用,弹窗的弹出与敞开等等。
  • 不依赖各种第三方框架,不必学习它们,也不受它们的束缚。
  • UI 和 Router 之间没有间接绑定,而是通过 State 映射,这意味着如果产品优化、路由格局变动,改变的只是映射,而不必动到 View 和 State,这样更涣散。

理论案例

以上所说只是一个大体思路,真正要用得不便,还得做一些细节的封装和改变,这里提供一个本人的开源我的项目供大家参考,在线预览:http://admin-react-antd.eluxj…

该我的项目中,没有应用任何第三方 Router 框架,全凭本人撸,那感觉也挺好的 …😂😂😂

  • React 版本

    • github: https://github.com/hiisea/elu…
    • gitee: https://gitee.com/hiisea/elux…
  • Vue 版本

    • github: https://github.com/hiisea/elu…
    • gitee: https://gitee.com/hiisea/elux…

另外将这种手撸机制,天马行空的与 Dialog 联合,就诞生出一个神器:虚构 Window,能够查看我的另一篇文章:【不想当 Window 的 Dialog 不是一个好 Modal,弹窗翻身记 …】

退出移动版