Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

基于React Router的SPA单Route下多view切换方案 #3

Open
jnotnull opened this issue Jul 14, 2017 · 0 comments
Open

基于React Router的SPA单Route下多view切换方案 #3

jnotnull opened this issue Jul 14, 2017 · 0 comments

Comments

@jnotnull
Copy link
Owner

jnotnull commented Jul 14, 2017

场景:针对查询消息历史记录,广播消息事件下有多个群,每个群下有对应的动作,三个view之间的关系如下 eventlist => roomlist => actionlist,点击某个event到达roomlist,点击某个room到达actionlist。因为这三者(eventlist, roomlist, actionlist)依赖关系比较强,而且会被多个地方调用,他们三者就封装为一个组件(Component)了。随着点击的深入,如何返回到上一级就变成现实的问题了,即使你在组件中提供了返回按钮,也不能保证用户那天不点击浏览器的返回按钮。

现有解决方案:

  1. 使用弹出框

    这个在PC端还行,在H5端反复的弹出框就显得蛋疼了, say no。

  2. 服务端渲染

    依靠服务端渲染,由服务端提供基础路由。改动量太大,say no。

  3. 改成多页应用

    这个和服务端渲染类似,只是基础路由由文件夹路径提供而已,改动还是大,say no。

  4. 使用React-Router的childRoutes属性,定义不同路由指向不同的Component,但是面临的问题就是要把组件打散,分配配置每个child路由对应的Compoent,也就是说这里的公共组件至少拆分成三个,而且还不好解决组件共用问题,fuck,这我哪能受得了,say no。

最终方案:BrowerHistory + hash

BrowerHistory提供基础路由,比如这里的广播消息,hash负责分开的试图,这里定义两个hash:#roomlist和#actionlist,hash为空代表进入的是eventlist view。

注意,这里我说的是hash,不是HashHistory,因为React-Router本身只提供一种路由方案,不能混合使用,这里的hash是浏览器原生的location hash。

关于BrowerHistory的配置和用途这里不做说明,下面开始我们的路由之旅。

首先进入到eventlist view。由于点击某个event要进入roomlist,我们绑定下事件:

<span className={styles.process} onClick={this.viewrooms.bind(this, item)} >
{item.ext.status}
</span>

viewrooms方法中修改URL中hash

viewlogrooms(item){
    history.pushState({}, '', '#roomlist');
    let room_ids = item.room_ids;
    queryrooms({room_ids})
}

注意:这里我们我们是前进的过程,使用的是history.pushState,它不会触发window的popstate事件,popstate触发我们用在浏览器点击返回的时候使用。关于onpopstate更多资料,请参考 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/onpopstate

而在这里增加hash会触发React-Router监听,在这里我们做下保护,如果有hash则不执行,这样带来的问题是不能带上hash去刷新了。处理方法很暴力,加上location.hash = ''; ,这样就能重新返回到基础路由上了。

{
   path: urlprefix + '/ctrldeskbroadcast',
   name: 'ctrldeskbroadcast',
   getComponent(nextState, cb) {
      if (location.hash) {
        location.hash = '';
        return false;
      }
     require.ensure([], require => {
       registerModel(app, require('./models/ctrldeskbroadcast'));
       cb(null, require('./routes/ctrldeskbroadcast'));
     });
   },
 },

当用户点击浏览器返回按钮时候,会触发onpopstate事件,我们在这里做监听,对view进行切换

window.onpopstate = ()=> {
    if(this._isMounted) {
        const { hash } = location;
        ...
        this.refs.logevent.handlecancelfun();
    }
}

这样就能够完美的实现单个路由下多个view的切换了。

@jnotnull jnotnull changed the title 单页应用中的单Route下多hash路由方案 SPA中的单Route下多hash路由方案 Jul 15, 2017
@jnotnull jnotnull changed the title SPA中的单Route下多hash路由方案 基于React Router的SPA单Route下多hash路由方案 Jul 15, 2017
@jnotnull jnotnull changed the title 基于React Router的SPA单Route下多hash路由方案 基于React Router的SPA单Route下多view切换方案 Jul 15, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant