ToolJet Switch Page 动作详解:多页面应用中的页面跳转、Query Params 与 RunJS 编程调用
【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet
Switch Page 是 ToolJet 多页面(Multipage)应用中用于在页面之间进行导航的核心动作(Action),可挂载在按钮等组件的各类事件处理器上,也可通过 RunJS 查询以编程方式触发。本文将以 v3.0.0-LTS 版本文档为主体,结合仓库前端源码,完整讲解 Switch Page 的配置方式、Query Params(查询参数)的传递机制、RunJS 调用语法以及底层实现原理,帮助你掌握多页面应用中的页面跳转实战方案。
Switch Page 动作概览
ToolJet 允许在单个应用内创建多个页面,使应用更易于导航和更友好(参见 Pages 教程)。Switch Page 动作的作用就是将用户从当前页面过渡到应用内的另一个页面,它可以挂载到各种组件的事件处理器(Event Handler)上,例如按钮的On Click事件。
在动作配置面板中可以看到以下关键字段:
- Page Handle:目标页面的句柄(slug)。页面句柄是追加在应用 URL 末尾的路径片段,默认是页面名称的小写形式、空格替换为连字符,可在页面的 kebab 菜单中通过 Edit 图标修改(见 Pages 文档)。
- Debounce(防抖):默认留空,可输入一个数值表示动作执行前等待的毫秒数,例如
300表示延迟 300ms 后执行。防抖常用于避免用户快速重复点击导致页面频繁切换。 - Query Params(查询参数):可附加在切换后页面 URL 上的键值对参数,详见下文。
提示:Pages 面板中每个页面都有独立的暴露变量,包括
handle、name、id和variables,可通过{{page.handle}}、{{page.name}}、{{page.id}}、{{page.variables.<pageVariableName>}}动态访问(见 Pages 文档的 Exposed variables 小节)。这些变量可以在设置 Switch Page 动作时作为参考。
配置 Query Params(查询参数)
Switch Page 动作支持向目标页面传递查询参数。查询参数会被追加到应用 URL 末尾,并以问号(?)开头。
参数格式
查询参数由键值对组成,key与value之间用等号(=)分隔。点击动作配置面板中的+按钮可以添加多组查询参数,最终生成的 URL 中多组参数之间以&连接。
例如配置一组参数后,切换页面的 URL 会形如:
https://your-domain/applications/<app-slug>/<page-handle>?username=user@example.com使用动态值
查询参数的值支持 ToolJet 的表达式语法(双花括号{{ }}),可以引用组件状态、全局变量等。官方示例中,以username作为 key,value 设置为{{globals.currentUser.email}},即可动态获取当前登录用户的邮箱:
key: username value: {{globals.currentUser.email}}当点击按钮触发挂载在它上面的 Switch Page 事件处理器后,切换到的页面 URL 就会携带username=<当前用户邮箱>这样的参数。这种方式常用于:
- 向服务端传递附加信息;
- 修改目标页面的行为(例如预填充筛选条件);
- 过滤搜索结果、分页、排序等场景。
通过 RunJS 查询切换页面
除了在事件处理器中可视化配置,Switch Page 动作还可以通过 RunJS 查询以代码方式触发。关于如何在 RunJS 查询中运行各种动作的完整指南,可参考 Run Actions from RunJS Query。
基本语法
在 RunJS 查询中使用actions.switchPage函数,传入目标页面的句柄(page handle):
await actions.switchPage('<page-handle>')注意这里使用的是页面句柄(slug)而非页面名称。例如页面名为 "Dashboard"、句柄为dashboard,则调用await actions.switchPage('dashboard')。
携带查询参数切换
Switch Page 动作也可以在切换的同时携带查询参数,语法为传入一个由键值对数组构成的二维数组:
actions.switchPage('<pageHandle>', [['param1', 'value1'], ['param2', 'value2']])其中param1、param2是查询参数名,value1、value2是对应的值,可以替换为任意合法的参数名和值(同样支持表达式求值)。生成的 URL 中会以?param1=value1¶m2=value2的形式附加。
从仓库前端源码的代码提示常量表可以看到,switchPage是应用构建器中可供 RunJS 使用的内置动作之一(见 actions.js),该文件是代码提示(code hints)中可用动作的单一事实来源(single source of truth)。
源码视角:Switch Page 的底层实现
要深入理解 Switch Page 动作的行为,可以查看其核心实现。前端状态管理中switchPage的实现在 appSlice.js,其函数签名如下:
switchPage: (pageId, handle, queryParams = [], moduleId = 'canvas', isBackOrForward = false) => { ... }从源码结构看,一次页面切换主要经历以下过程:
- 防重复切换守卫:通过
pageSwitchInProgress标志位防止快速连续触发。若切换正在进行,会弹出提示 "Please wait, page switch in progress" 并直接返回;该标志会在切换前同步置位,避免并发调用绕过守卫。 - 加载态展示:设置页面加载器(
setPageLoader(true)),并通过yieldToMain()让出主线程,确保加载器先绘制出来再执行后续重活。 - 状态清理与切换:清理旧页面存储(
cleanUpStore)、清理临时布局(clearTemporaryLayouts)、更新当前页面 ID、组件名映射和查询映射(setCurrentPageId、setComponentNameIdMapping、setQueryMapping),并重新初始化依赖图(initDependencyGraph)。 - 查询参数过滤:对传入的查询参数进行过滤——值为空的参数会被剔除;
env参数仅在 License 有效时保留(frontend/src/AppBuilder/_stores/slices/appSlice.js#L331-L335)。 - URL 构造与导航:将查询参数拼接为
key=value&...形式的字符串,结合应用 slug、subpath、workspace 等信息构造目标 URL 并执行navigate(预览模式走/applications/<slug>/<handle>,编辑模式走/<workspaceId>/apps/<slug>/<handle>),同时通过state传递页面切换信息。 - 全局状态更新:更新页面对应的已解析常量(
setResolvedPageConstants,包含id、handle、name),并将解析后的查询参数写入全局urlparams(setResolvedGlobals('urlparams', ...)),供目标页面通过{{globals.urlparams}}读取。
若切换的是同一页面(isSamePage为 true),还会生成新的pageKey(UUID)以强制触发页面级刷新逻辑(appSlice.js)。
事件处理器中的解析与拦截
当通过事件处理器触发 Switch Page 时,实际执行路径在 eventsSlice.js。该实现中值得注意的细节:
- 参数解析:
queryParams中的每个键值对都会通过getResolvedValue先解析(支持表达式),再传给switchPage。 - 保留 version 与 env:如果当前 URL 中带有
version或env查询参数,而目标参数中没有,则会将它们自动补充到解析后的参数列表首位,确保切换页面时版本/环境信息不丢失。 - 受限页面拦截:如果目标页面设置了访问受限(
page.restricted)且当前不是编辑模式,会提示 "Access to this page is restricted. Contact admin to know more." 并中止切换。 - 禁用页面拦截:如果目标页面被禁用(
page.disabled),会提示 "Page is disabled",同时在调试器中记录一条错误日志(navToDisablePage)。
这与 Pages 文档 中的说明一致:被隐藏(Hide Page)的页面虽然不出现在导航侧边栏,但仍可通过 Switch Page 动作或页面 URL 直接访问;而被禁用(Disable Page)的页面在 viewer 模式下不可访问。
典型使用场景
结合文档与源码,Switch Page 动作的典型场景包括:
| 场景 | 实现方式 |
|---|---|
| 按钮点击跳转到另一页 | 在按钮On Click事件处理器中添加 Switch Page 动作,选择目标页面句柄 |
| 跳转并携带筛选条件 | 在 Query Params 中配置如status=active,或 value 使用{{components.table1.selectedRow.status}}等动态表达式 |
| 登录后携带用户信息跳转 | value 使用{{globals.currentUser.email}}动态获取当前用户邮箱 |
| 逻辑判断后编程跳转 | 在 RunJS 查询中调用await actions.switchPage('orders', [['status', 'pending']]) |
| 页面加载事件跳转 | 在页面的On page load事件处理器中使用 Switch Page(页面也可挂载事件处理器,见 Pages 文档的 Event Handlers 小节) |
注意事项与最佳实践
- 句柄而非名称:RunJS 调用时第一个参数必须是目标页面的句柄(可在页面 kebab 菜单中查看/修改),不是页面显示名称。
- 防抖字段:若需防止快速重复切换,可在动作配置中为 Debounce 字段设置毫秒值(如
300);源码层面也有pageSwitchInProgress防并发保护。 - 动态值求值:Query Params 的 key 和 value 均支持
{{ }}表达式,事件处理器触发时会先通过getResolvedValue解析再拼入 URL。 - 版本与环境参数自动保留:从源码实现看,切换页面时当前 URL 中的
version、env参数会被自动带到目标页,无需手动重复配置。 - 受限/禁用页面不可切换:受限页面在非编辑模式会拦截跳转,禁用页面在 viewer 模式不可访问;主页(Home)不能被隐藏或禁用,但可以被 Switch Page 跳转。
- 通过 URL 直接访问:切换后的页面 URL 形如
.../<app-slug>/<page-handle>?key=value,该 URL 本身也可用于直接访问或分享特定页面。
延伸阅读
- Pages 教程:多页面应用与页面句柄
- Run Actions from RunJS Query:在 RunJS 中调用各类动作
- 动作底层实现:appSlice.js 中的 switchPage、eventsSlice.js 中的事件触发逻辑
- 动作列表单一事实来源:frontend/src/AppBuilder/_stores/constants/actions.js
- 相关页面动作文档:Set Page Variable、Unset Page Variable、Go to App
【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考