有没有发现,在大家应用 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 局部,pathname
和query
,有很多第三方库提供解析它们的办法,比方:
-
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 />}
</>
);
};
发动路由跳转
基于 pushState
和replaceState
,封装一下就能够了:
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,弹窗翻身记 …】