写点什么

手撸 Router,还要啥 Router 框架?让 react-router/vue-router 躺一边凉快去

作者:hiisea
  • 2022 年 8 月 03 日
  • 本文字数:1722 字

    阅读完需:约 6 分钟

手撸Router,还要啥Router框架?让react-router/vue-router躺一边凉快去

有没有发现,在大家使用 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,有很多第三方库提供解析它们的方法,比如:



  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.eluxjs.com/


该项目中,没有使用任何第三方 Router 框架,全凭自己撸,那感觉也挺好的...😂😂😂



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

用户头像

hiisea

关注

还未添加个人签名 2022.06.13 加入

Elux-基于“微模块”和“模型驱动”的跨平台、跨框架同构方案

评论

发布
暂无评论
手撸Router,还要啥Router框架?让react-router/vue-router躺一边凉快去_vue.js_hiisea_InfoQ写作社区