拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Taro H5 端路由系统解析:从 `@tarojs/router` 看小程序路由规范在 Web 端的落地

Taro H5 端路由系统解析从tarojs/router看小程序路由规范在 Web 端的落地【免费下载链接】taro开放式跨端跨框架解决方案支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。 https://taro.zone/项目地址: https://gitcode.com/NervJS/taro导读tarojs/router是 Taro 框架 H5 端的路由系统核心包负责在浏览器中复刻微信小程序的路由与页面生命周期规范使同一套业务代码在 H5 与小程序端表现一致。本文以 packages/taro-router/README.md 为骨架深入其源码packages/taro-router/src系统讲解createRouter核心 API、路由模式、页面栈、导航 API 与生命周期兼容的实现原理帮助开发者理解 H5 端路由配置h5.router的每一项参数背后发生了什么。一、tarojs/router是什么在 Taro 的架构中tarojs/router承担 H5 端“路由 页面生命周期调度”的职责。它的定位非常明确——不是普通的前端路由库而是一套兼容小程序路由规范的应用引导器小程序中页面通过wx.navigateTo、wx.switchTab、wx.redirectTo、wx.reLaunch、wx.navigateBack跳转小程序中 App 拥有onLaunch/onShow/onHide页面拥有onLoad/onShow/onHide/onUnload等生命周期H5 端浏览器只有history与location没有页面栈概念。tarojs/router的作用就是用浏览器能力模拟出这套“页面栈 生命周期 路由跳转 API”从而让 Taro 编译到 H5 后业务代码无需感知运行环境差异。包信息可在 packages/taro-router/package.json 中查看其依赖了history^5.3.0、universal-router^9.2.0、query-string等并声明node 18。说明本文引用的源码位于packages/taro-router/src类型定义位于 packages/taro-router/types单元测试位于 packages/taro-router/tests。二、核心 APIcreateRouter2.1 文档定义的签名根据 packages/taro-router/README.md核心 API 为createRouter(app, config, type, framework, reactDOM)它被暴露给tarojs/taro-loader/h5调用在应用入口文件中执行用于创建一个兼容小程序路由规范的应用。各参数含义参数类型说明app组件入口文件默认导出的组件App 根组件config对象应用全局配置及页面配置对应app.config.js与page.config.js的返回内容type字符串框架类型react|vue|solid|preact四选一framework对象框架的 default import 对象reactDOM对象可选react-dom的 default import 对象2.2 源码中的真实调用链从当前源码看H5 入口代码由 packages/taro-loader/src/h5.ts 生成其第 116150 行组装了完整的启动序列const routerCreator isMultiRouterMode ? createMultiRouter : createRouter const historyCreator routerMode browser ? createBrowserHistory : routerMode multi ? createMpaHistory : createHashHistory const appMountHandler config.tabBar ? handleAppMountWithTabbar : handleAppMount // ... var inst creator(component, frameworkArgs) // 创建 App 实例 var history historyCreator({ window }) // 按模式创建 history appMountHandler(config, history) // 挂载 #app 容器含 TabBar 时走 TabBar 版 routerCreator(history, inst, config, importFrameworkName) // 启动路由由此可见在当前代码库中createRouter的实际运行时签名是createRouter(history, app, config, framework)见 packages/taro-router/src/router/spa.tshistory 对象在最前面随后才是文档所述的 app、config、framework。读者在阅读 README 的 API 描述时应结合此调用链理解——README 描述的是面向业务的“契约语义”loader 负责把真实的依赖history注入进来。2.3createRouter内部做了什么packages/taro-router/src/router/spa.ts 的启动流程可分为四步注册全局错误监听若 App 定义了onUnhandledRejection挂载unhandledrejection事件若定义了onError挂载error事件。构建路由表将config.routesloader 根据app.config.js的pages生成每个页面是一个{ path, load }load为动态 import交给universal-router同时把router.customRoutes别名写入routesAlias实现“一个真实路径对应多个 URL”。触发启动生命周期构造launchParampath/query/scene 等后依次触发__taroRouterLaunch事件与app.onLaunch。监听路由变化通过history.listen(render)订阅地址变化render中根据 actionPUSH/POP/REPLACE与目标路径维护页面栈、挂载/卸载页面实例。createRouter返回的正是history.listen(render)的取消订阅函数。2.4 配套挂载函数handleAppMount与handleAppMountWithTabbar在 packages/taro-router/src/index.ts 中有两个供 loader 调用的挂载函数handleAppMount(config, history, appId app)查找或创建#app容器并添加taro_router类然后调用initNavigationBar初始化导航栏。handleAppMountWithTabbar(config, history, appId)额外创建taro-tabbar__container/taro-tabbar__panel结构包裹页面容器先initTabbar再initNavigationBar。loader 会根据config.tabBar是否存在自动选择packages/taro-loader/src/h5.ts。三、路由配置h5.router各参数与源码对应H5 端路由配置类型定义在 packages/taro/types/compile/config/h5.d.ts在 packages/taro-router/types/router.d.ts 中进一步约束为Router接口。常用配置如下配置项类型默认值作用modehash \| browser \| multihash路由模式basenamestring/路由基准路径如部署在子目录/taro/下customRoutesRecordstring, string \| string[]{}自定义路由映射可把复杂路径映射为短路径forcePathstring无强制指定解析的路径enhanceAnimationboolean无解决返回页面白屏问题依赖:has()选择器这些配置在 packages/taro-router/src/router/index.ts 的RouterConfig静态类中被统一读取例如mode默认hashcustomRoutes默认{}。3.1mode三种路由模式的选择逻辑setHistoryModepackages/taro-router/src/history.ts是模式分发的核心if (mode browser) { history createBrowserHistory(options) // HTML5 History APIURL 无 # } else if (mode multi) { history createMpaHistory(options) // 多页面模式见下文 } else { history createHashHistory(options) // hash 模式默认 }hash 模式默认URL 形如/#/pages/index/index无需服务端配置适合静态托管。browser 模式URL 为真实路径需要服务端将未知路径回退到index.html。multi 模式多页面MPA每个页面一个独立 HTML对应createMultiRouter见 packages/taro-router/src/router/mpa.ts。3.2basename的处理history.ts中通过prependBasename给所有跳转 URL 拼接 basenameSPA 启动时若history.location.pathname去除 basename 后等于/会通过history.replace重定向到homePagepackages/taro-router/src/router/spa.ts保证首屏命中配置的entryPagePath。3.3customRoutes的别名机制routesAliaspackages/taro-router/src/utils/index.ts维护真实路径与 URL 别名之间的双向映射getAlias(url)把真实路径转为对外 URL/pages/index/index→/indexgetOrigin(url)反向解析/index→/pages/index/indexgetAll(url)返回该路径对应的全部别名数组SPA 中会把同一路径的所有别名作为universal-router的多条匹配规则。在processNavigateUrlpackages/taro-router/src/api.ts中导航 URL 会依次经过相对路径归一化./、../→ 补前导/→ 别名替换 → basename 拼接最终交给 history。3.4multi模式MPA的特有实现createMultiRouterpackages/taro-router/src/router/mpa.ts与 SPA 路由差异明显其源码注释明确列出了限制需要配置路由映射根目录跳转、404 页面……app.onPageNotFound事件不支持应用生命周期可能多次触发每打开一个页面相当于一次重启TabBar 会多次加载不支持路由动画。MPA 模式下 loader 不再生成整个config.routes数组而是只注入当前页的config.route与config.pageNamepackages/taro-loader/src/h5.tshistory 则使用自定义的MpaHistorypackages/taro-router/src/history.ts通过window.location.assign实现整页跳转并用popstate 自定义pushState/replaceState事件模拟 history 监听页面 URL 会在命中 pages 时自动追加.html后缀。四、页面栈与导航 API4.1 页面栈实现页面实例栈由 packages/taro-router/src/router/stack.ts 的Stacks类维护push / pop / getItem / length / last栈的基础操作getLastIndex(pathname)从栈顶向下查找某路径最后一次出现的位置用于浏览器后退多级时计算deltagetDelta(pathname)结合backDeltanavigateBack传入返回应卸载的页面数量tabsTabBar 页面的缓存实例pushTab / popTab / getTabs / removeTab管理其生命周期。SPA 的render逻辑packages/taro-router/src/router/spa.ts根据导航意图分派reLaunch卸载当前页并清空 TabBar 缓存页进入 TabBar 页隐藏当前页、缓存/恢复 Tab 页面实例同页跳转直接 returnPOP浏览器后退计算 delta 卸载页面并通过__taroPageOnShowAfterDestroyed事件延迟触发上一页onShow修复 Safari 额外 POP 事件导致的误卸载REPLACE卸载当前页后加载新页PUSH隐藏当前页并加载新页。另外源码在第 3841 行对“弱网快速切换 Tab 导致同页实例重复挂载”的问题加了pageLock锁异步加载完成后会校验currentLock ! postLock不一致则丢弃本次渲染结果。4.2 导航 API 与小程序对齐packages/taro-router/src/api.ts 导出了与小程序同名的五个 APIAPI底层实现说明navigateTohistory.push打开新页面可携带events并通过eventChannel与目标页通信redirectTohistory.replace关闭当前页跳转到新页switchTabhistory.replace跳转到 TabBar 页面并关闭其他非 Tab 页面reLaunchhistory.replacestacks.delta length关闭所有页面打开指定页navigateBackhistory.go(-delta)返回delta默认 1小于 1 时强制为 1navigate内部统一返回 Promise通过一次性的history.listen在跳转完成后回调success/completenavigateTo还会把EventChannel.routeChannel注入返回结果供eventChannel.emit实现页面间数据传递。getCurrentPages()返回页面栈的浅拷贝route字段去掉 query在multi模式下会console.warn提示不支持packages/taro-router/src/api.ts。五、小程序生命周期与路由事件的兼容5.1 App 生命周期SPA 与 MPA 的启动代码中都实现了小程序 App 生命周期的映射onLaunch(launchParam)启动时触发参数包含path、query、scene: 0、shareTicket: 、referrerInfo: {}onShow / onHide通过监听visibilitychange页面可见性变化触发同时补发当前页面的onShow / onHide见 packages/taro-router/src/router/spa.tsonError(message)监听 windowerror事件onUnhandledRejection监听unhandledrejection事件onPageNotFound(event)仅 SPA 支持universal-router解析抛出 404 时触发事件包含isEntryPage、path、query。5.2 路由事件路由系统通过tarojs/runtime的eventCenter广播以下内部事件SPA 场景事件名触发时机消费方__taroRouterLaunch应用启动携带 launchParam__taroRouterChange每次路由变化前携带{ toLocation: { path } }__taroRouterNotFound404 页面携带{ isEntryPage, path, query }__taroSetNavigationStyle页面配置变化携带navigationStyle等导航栏样式__taroH5SetNavigationBarTitle设置标题导航栏与setMpaTitle5.3 页面级配置的读取优先级SPA 渲染时页面级配置enablePullDownRefresh、navigationStyle、navigationBarTextStyle、navigationBarBackgroundColor遵循“全局 window 配置为默认值、页面配置覆盖”的规则packages/taro-router/src/router/spa.ts并在之后通过__taroSetNavigationStyle事件下发给导航栏组件。下拉刷新开启时会通过hooks.call(createPullDownComponent, ...)用框架对应的PullDownRefresh组件包装页面。六、源码验证测试与类型约束单元测试位于 packages/taro-router/testsrouter-test.tsx覆盖了createRouter的调用方式——直接以{ entryPagePath, router: { mode, basename, customRoutes }, routes }作为 config 启动验证customRoutes映射/pages/index/index→/index、Taro.navigateTo后页面显隐切换以及this.$router参数注入history-test.tsx覆盖 history 模块行为。对外类型定义集中在 packages/taro-router/typesrouter.d.ts定义Route / Router / SpaRouterConfig / MpaRouterConfigapi.d.ts定义导航选项Option、NavigateBackOption、NavigateOptionhistory.d.ts定义 history 相关类型。顶层导出packages/taro-router/src/index.ts对外提供createRouter、createMultiRouter、handleAppMount、handleAppMountWithTabbar、导航 API、history 工厂createBrowserHistory / createHashHistory / createMpaHistory / setHistoryMode以及setTitle / setNavigationBarStyle / setNavigationBarLoading等工具函数。七、总结tarojs/router通过createRouterSPA与createMultiRouterMPA两个入口把小程序“页面栈 路由跳转 生命周期”规范完整移植到浏览器三种路由模式hash / browser / multi由h5.router.mode一键切换底层对应createHashHistory / createBrowserHistory / createMpaHistorycustomRoutes与basename在加载器、history、universal-router 三层协同工作五个导航 API 与getCurrentPages保持与小程序一致的调用语义App/Page 生命周期与内部路由事件通过eventCenter完整贯通。对开发者而言理解本文所述的实现细节后可以更准确地使用 packages/taro/types/compile/config/h5.d.ts 中的h5.router配置也能在排查 H5 端“后退白屏”“Tab 页面状态丢失”“MPA 生命周期异常”等问题时快速定位到 packages/taro-router/src/router/spa.ts、packages/taro-router/src/router/stack.ts 等对应模块。【免费下载链接】taro开放式跨端跨框架解决方案支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。 https://taro.zone/项目地址: https://gitcode.com/NervJS/taro创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门