# 前言

本章节内容分解:

  • 小程序路由设计
  • webview与路由栈

# 路由

在渲染层中可以看到这一段代码,具体位置在generateFuncReady函数前面,直接搜索history也可以找到。

History.pushState('', '', 'http://127.0.0.1:37434/__pageframe__/pages/index/index');

image.png

将pages/index/index地址推入路由堆栈,页面路由就此诞生。这里让我想起了SPA最开始的路由形式。这种history.pushState的方法并不像我们在react 或者 vue中使用的那样,但是底层原理都是一样的。

这里我们可以展开讲解一下。

回顾一下小程序页面加载的原理,如果我们跳转到一个新页面,那么在渲染层中会插入一个webview,渲染层中可以有多个webview。

采用多个webview这种方式类似于多页面应用,而不是单页面应用,因为多页面应用可以保留前一个页面的状态,现在小程序页面跳转的方式可以参考app,新页面都是从右侧向左划入的。所以路由的内部是基于多页应用的架构实现的,基于这个原理路由其实并不复杂。

首先触发路由的行为是可以从渲染层发出,也可以从逻辑层发出。在渲染层中用户可以通过点击回退按钮,或者回退上一页的手势等机制触发。

在逻辑层中发出的信号有打开新页面navigateTo、重定向redirectTo、页面返回navigateBack等,开发者通过官网提供的API触发。

无论是渲染层用户触发的行为,还是逻辑层API触发的行为,这个行为都会被发送到Native层,有Native层统一控制路由。

在微信小程序中页面为webview形式,并且是多个webview叠加的形式,所以路由的打开新页面行为对应添加一个新的webview并且覆盖在前一个webview的上面,并初始化新页面的生命周期。其他宿主环境和承载UI页面的容器原理与此方案一致。顺推,页面返回的行为相对应移除一个webview。

这里对于webview的添加或删除都会有一个载体来维护,这就是路由栈。

打开新页面就会往路由栈上方推入一个页面,删除则从栈顶依次删除。并且前面我们了解到webview不可以无限插入,因为这种多页面形式会有性能问题,所以路由栈有最大的插入限制。退回的话最多删除stack.length - 1个,也就是最多回退到首页。

路由架构.png

上图演示了打开页面的路由内部流程,配合pageFrame创建新webview。逻辑层中发出打开页面行为到Native层,Native层收到行为后通过pageFrame快速创建webview,并且推入路由栈。页面创建完后,底层基础库会立刻执行初始化操作,初始化完毕后会发送一个信号通知Native页面已经创建并初始化完毕,随后Native层发送信号到逻辑层中。之所以这样设计流程是因为有两个目的:

  • 需要通知开发者页面已经创建成功。
  • 在沙箱中创建新页面的“根组件”,并正式开启新页面的生命周期与渲染的流程。

下面总结一下在小程序场景中路由变化相对应的栈变化:

  • 小程序初始化的时候需要推入首页,新页面入栈。
  • 打开新页面对应 navigateTo,新页面入栈
  • 页面重定向 redirectTo,当前页面出栈,而后新页面入栈。
  • 页面回退navigateBack,页面一直出栈,到达指定页面停止。
  • Tab切换switchTab,页面全部出栈,只留下新的Tab页面。
  • 重新加载 reLaunch,页面全部出栈,只留下新的页面。

最后附带一下官网注意事项:

  • navigateTo, redirectTo 只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
  • 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
  • 调用页面路由带的参数可以在目标页面的onLoad中获取。
阅读全文