有没有发现,在大家使用React/Vue的时候,总离不开一个小尾巴,到哪都得带着他,那就是react-router/vue-router,而基于它们的第三方框架又出现很多个性化约定和扩展,比如nuxtjs/nextjs/umijs都纷纷推出自己的路由方案。 有没有发现,在大家使用React/Vue的时候,总离不开一个小尾巴,到哪都得带着他,那就是react-router/vue-router,而基于它们的第三方框架又出现很多个性化约定和扩展,比如nuxtjs/nextjs/umijs都纷纷推出自己的路由方案。
有没有想过,其实你可以完全摆脱他们都束缚?而且并不复杂,下面听我来分析分析:
首先React/Vue都是基于MVVM架构,State可以决定Component的显示与否,而且很简单:
// jsx{show? <SubUI /> : null}// vue<SubUI v-if="show" />也可以根据State来动态显示组件:
<component :is="componentA"></component>控制UI的方法有很多,我就不例举了,总之State才是掌控UI的大脑中枢。
路由的作用,无非就是根据Url来控制UI展示,那么你只需要将Url映射成为State,不就达到目的了?
Url主要分2部分,pathname和query,有很多第三方库提供解析它们的方法,比如:
const regexp = pathToRegexp("/:foo/:bar");regexp.exec("/test/route");具体用法大家看看官方文档就可以了,很简单...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 = render(state),路由和其它因子都被挡在外围,当作一种影响State的副作用之一。以上所说只是一个大体思路,真正要用得方便,还得做一些细节的封装和改动,这里提供一个自己的开源项目供大家参考,在线预览:http://admin-react-antd.eluxjs.com/
该项目中,没有使用任何第三方Router框架,全凭自己撸,那感觉也挺好的...??????