频道栏目
首页 > 资讯 > 微信小程序 > 正文

小程序无限层级路由方案(无框架依赖)教程

19-01-16        来源:[db:作者]  
收藏   我要投稿
  • 小程序历史栈最多只支持10层

    当小程序业务比较复杂时,就很容易超过10层。

    当超过10层后,有的机型是点击无反应,有的机型会出现一些未知错误

    为了解决这些问题,我们引入了无限层级路由方案。

    方案

    首先声明一下,最初方案并不是我提出的,是我司内部一位清华学霸提出的。但他们是基于wepy框架做的处理,由于我们用的是mpvue,所以对这个方案上做了修改,同时不依赖于框架。

    虽然是改造版,但原理是一样的,下面我来介绍一下修改后的方案。

    几个关键点:

    9层(含9层)以内时:走小程序自己的历史栈就ok了,跳转时候更新一下逻辑栈,这没啥可说的

    从9层跳转10层:需要把第9层重定向到中转页,再由中转页跳转到10层

    10层以后跳转:在navigateTo方法中处理,到10层之后,再跳转就第10层页面一直做redirectTo(重定向)操作了

    10层以上返回:会返回到中转页,由中转页判断,具体返回到哪个页面,然后navigateTo(跳转)过去

    从10层返回到9层:返回到中转页,将中转页redirectTo(重定向)到第9层页面

    9层内的返回:直接返回就好了,返回时候不会更新逻辑栈,但没有关系,因为只有中转页才会用到逻辑栈

    逻辑栈更新机制:

    跳转、返回中转页时更新

    navigateTo时更新

    redirectTo时更新

    reLaunch时更新

    navigateBack时更新

    图示:

    用户操作

    小程序历史栈

    js逻辑栈:自行维护的js路由栈

    “中”表示中转页

    “1 2 3 4 5 6 7 8 9 A B C”表示不同的页面路径

     

     

    之前跳转操作和10层以上的返回操作都会更新逻辑栈,到了10层以内的返回操作就不会更新逻辑栈了。到这里细心的读者可能已经发现:

    原因:

    这块也是我们对原有方案的主要改造点。因为到了10层以内,所有的返回和跳转都由微信系统历史栈接管了。

    我们只要保证用户在通过api进行跳转操作时更新就可以了。而且,自己维护的逻辑路由栈实际上只有中转页才会用到。

    这样也就不用在每个页面都要注册onUnload钩子去实时更新返回时的路由信息了。把更新路由信息的逻辑都放到了api调用这一层。业务开发时完全不用关心。

    示意代码

    lib/navigator/Navigator.js (自己封装的跳转方法, History.js代码省略了)

    ...

    import History from '@/lib/navigator/History'

    const MAX_LEVEL = 10 // 小程序支持打开的页面层数

    export default class Navigator {

    // 中转页面路径

    static curtainPage = '/pages/curtain/curtain/main'

    // 最大页数

    static maxLevel = MAX_LEVEL

    // 逻辑栈

    static _history = new History({

    routes: [{ url: '' }],

    correctLevel: MAX_LEVEL - 2

    })

    ...

    /**

    * 打开新页面

    * @param {Object} route 页面配置,格式同wx.navigateTo

    */

    @makeMutex({ namespace: globalStore, mutexId: 'navigate' }) // 避免跳转相关函数并发执行

    static async navigateTo (route) {

    console.log('[Navigator] navigateTo:', route)

    // 更新逻辑栈

    Navigator._history.open({ url: route.url })

    let curPages = getCurrentPages()

    // 小于倒数第二层时,直接打开

    if (curPages.length < MAX_LEVEL - 1) {

    await Navigator._secretOpen(route) // 就是调用wx.navigateTo

    // 倒数第二层打开最后一层

    } else if (curPages.length === MAX_LEVEL - 1) {

    const url = URL.setParam(Navigator.curtainPage, { url: route.url })

    await Navigator._secretReplace({ url }) // wx.redirectTo 到中转页,再由中转页跳转到第10层页面

    // 已经达到最大层数,直接最后一层重定向

    } else {

    await Navigator._secretReplace(route) // wx.redirectTo 第10层页面直接重定向

    }

    }

    /**

    * 完整历史记录

    * @return {Array}

    */

    static get history () {

    return Navigator._history.routes

    }

    /**

    * 更新路由

    * @param {Object} config 自定义配置,可配置项参见 _config 相关字段及注释

    */

    static updateRoutes (routes = []) {

    this._history._routes = routes

    }

    ...

    }

    复制代码

    中转页代码 /pages/curtain/curtain/index.vue

    复制代码

    原理就是这样,但是有几点需要注意:

    业务代码中需要调用自己封装的跳转方法

    切记不要直接调用wx的api,也不要使用组件,这样是没法更新js逻辑栈的,正确跳转方式如:Navigator.navigateTo({ url: 'xxx' })。

    跳转时要及时更新js逻辑栈(更新时机如上所述),因为这会直接影响中转页的跳转逻辑

    这个方案最大的优点在于不用监听页面卸载时对逻辑栈的更新,无需在每个页面里加入更新逻辑栈代码。

    OK,这次就介绍这么多,有问题或者有更好的方案,可以留言沟通,大家相互学习。

相关TAG标签
上一篇:小程序不同页面之间通讯的解决方案教程
下一篇:小程序绑定事件跳转的三种方法的教程
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站