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

  • 手撸Router,还要啥Router框架?react-router/vue-router躺一边去已关闭评论
  • 16 次浏览
  • A+
所属分类:Web前端
摘要

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

有没有发现,在大家使用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的副作用之一。

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

  • 灵活性更高,你可以把URL映射成为任何State,从而控制任何State能控制的东西,比如用Url来控制一个按钮的启用与禁用,弹窗的弹出与关闭等等。
  • 不依赖各种第三方框架,不用学习它们,也不受它们的约束。
  • UI和Router之间没有直接绑定,而是通过State映射,这意味着如果产品优化、路由格式变动,改动的只是映射,而不用动到View和State,这样更松散。

实际案例

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

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