ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

GetX 路由管理完全指南:无 context 导航、命名路由、动态链接与嵌套导航

GetX 路由管理完全指南:无 context 导航、命名路由、动态链接与嵌套导航 前端【免费下载链接】getxOpen screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.项目地址https://gitcode.com/gh_mirrors/ge/getx点击查看免费下载本篇技术指南以 GetX 官方文档 documentation/pt_BR/route_management.md 为核心骨架结合当前仓库GitHub 加速计划 ge/getx中 get_navigation 模块的源码实现系统讲解 GetX 的路由与导航体系。你将掌握用Get.to系列 API 实现无 context 跳转、用GetMaterialAppGetPage构建命名路由、通过arguments与Get.parameters传递数据、实现类 Web 的动态 URL、接入路由 Middleware 监听、一键切换主题以及基于 ID 的嵌套导航最终让你的 Flutter 应用在不依赖BuildContext的前提下拥有完整、可维护的导航能力。目录一、无命名路由导航核心跳转 API二、SnackBars摆脱 Scaffold 与 context三、Dialogs 与 BottomSheets四、命名路由导航GetMaterialApp 与 GetPage五、向命名路由传参arguments 与动态 URL六、路由 Middleware监听与拦截导航事件七、Change Theme一键切换主题八、Get 的全局可选配置九、Nested Navigators按 ID 管理的嵌套导航栈一、无命名路由导航核心跳转 APIGetX 最直观的导航能力是把 Flutter 原生Navigator封装成静态方法调用全程不需要context。GetInterface的导航方法声明定义在 lib/get_navigation/src/routes/get_navigation_interface.dart 的IGetNavigationmixin 中实际实现位于 lib/get_navigation/src/extension_navigation.dart。1.1 基础跳转四件套API行为典型场景Get.to(ProximaTela())跳转到下一屏保留返回栈普通页面跳转Get.back()返回上一屏可关闭 snackbar/dialog/bottomsheet等价于Navigator.pop(context)Get.off(ProximaTela())跳转并移除当前页无法返回SplashScreen、登录页Get.offAll(ProximaTela())跳转并清空全部历史路由购物车、投票、测试等一次性流程Get.to(ProximaTela()); Get.back(); Get.off(ProximaTela()); // 好用于 SplashScreen、登录页等 Get.offAll(ProximaTela()); // 清空之前所有路由购物车、投票、测试场景从源码看Get.to等 API 的签名支持transition、curve、duration、opaque、popGesture、bindings、arguments、fullscreenDialog等参数见 get_navigation_interface.dart意味着你可以在一次调用中同时指定转场动画、参数与依赖注入这一点在后续章节会展开。1.2 从路由返回数据导航可以携带返回值这在填写表单后返回刷新等场景中非常实用// 第一屏等待返回结果 var dados await Get.to(Pagamento());// 第二屏把结果传回上一屏 Get.back(result: sucesso);// 第一屏使用结果 if (dados sucesso) fazerQualquerCoisa();1.3 不想学新语法直接换小写 navigator如果你对原生 API 更熟悉GetX 提供了一个零学习成本的过渡方案把Navigator大写换成navigator小写即可获得全部标准导航能力且无需context。这个顶层 getter 定义在 extension_navigation.dartNavigatorState? get navigator GetNavigationExt(Get).key.currentState;它直接取GetMaterialApp内部注册的NavigatorState。// Flutter 原生写法 Navigator.of(context).push( context, MaterialPageRoute( builder: (BuildContext context) { return HomePage(); }, ), ); // Get 的小写 navigator 写法无 context navigator.push( MaterialPageRoute( builder: (_) { return HomePage(); }, ), ); // Get 推荐语法更简洁 Get.to(HomePage());二、SnackBars摆脱 Scaffold 与 context原生 Flutter 展示 SnackBar 必须依赖Scaffold.of(context)或绑定在 Scaffold 上的GlobalKeyfinal snackBar SnackBar( content: Text(Olá!), action: SnackBarAction( label: Eu sou uma SnackBar velha e feia :(, onPressed: (){}, ), ); // 在 Widget 树中找到 Scaffold 并使用它展示 SnackBar Scaffold.of(context).showSnackBar(snackBar);用 GetX 只需要一行Get.snackbar(Olá, eu sou uma SnackBar moderna e linda!);Get.snackbar()的完整可定制参数来自原文档注释逐一对应源码实现Get.snackbar( Ei, eu sou uma SnackBar Get!, // 标题必填 É inacreditável! Eu estou usando uma SnackBar sem context, sem boilerplate, sem Scaffold!, // 消息必填 icon: Icon(Icons.alarm), shouldIconPulse: true, onTap:(){}, barBlur: 20, isDismissible: true, duration: Duration(seconds: 3), );完整参数清单类型即取值范围/语义// Color colorText, // 文字颜色 // Duration duration, // 展示时长 // SnackPosition snackPosition, // TOP / BOTTOM 位置 // Widget titleText, // 自定义标题 Widget // Widget messageText, // 自定义消息 Widget // bool instantInit, // 是否立即初始化 // Widget icon, // 左侧图标 // bool shouldIconPulse, // 图标是否脉冲动画 // double maxWidth, // 最大宽度 // EdgeInsets margin, // 外边距 // EdgeInsets padding, // 内边距 // double borderRadius, // 圆角 // Color borderColor, // 边框颜色 // double borderWidth, // 边框宽度 // Color backgroundColor, // 背景色 // Color leftBarIndicatorColor, // 左侧指示条颜色 // ListBoxShadow boxShadows, // 阴影列表 // Gradient backgroundGradient, // 背景渐变 // TextButton mainButton, // 主按钮 // OnTap onTap, // 点击回调 // bool isDismissible, // 是否可手动关闭 // bool showProgressIndicator, // 是否显示进度条 // AnimationController progressIndicatorController, // 进度条控制器 // Color progressIndicatorBackgroundColor, // 进度条背景色 // AnimationColor progressIndicatorValueColor, // 进度条颜色动画 // SnackStyle snackStyle, // 浮动 / 固定样式 // Curve forwardAnimationCurve, // 入场动画曲线 // Curve reverseAnimationCurve, // 退场动画曲线 // Duration animationDuration, // 动画时长 // double barBlur, // 背景模糊 // double overlayBlur, // 遮罩模糊 // Color overlayColor, // 遮罩颜色 // Form userInputForm // 内嵌表单如果你更喜欢传统 SnackBar或需要完全自定义例如单行布局可以使用Get.rawSnackbar()——它是Get.snackbar底层的原始 APIGet.snackbar正是基于它构建的。此外GetX 还提供了配套的状态查询与关闭 API见 extension_navigation.dartGet.isSnackbarOpen判断 SnackBar 是否正在展示Get.closeAllSnackbars()关闭全部Get.closeCurrentSnackbar()关闭当前。三、Dialogs 与 BottomSheets3.1 Get.dialog 与 Get.defaultDialog打开自定义 Dialog 只需传入任意 WidgetGet.dialog(SeuWidgetDialog());打开一个带默认样式的标准 DialogGet.defaultDialog( onConfirm: () print(Ok), middleText: Dialog made in 3 lines of code, );源码层面Get.dialog的实现位于 extension_navigation.dart 的ExtensionDialog扩展中它内部调用generalDialog并包裹SafeArea与Theme默认barrierColor为Colors.black54并支持通过transitionDuration、transitionCurve覆盖默认的淡入淡出动画FadeTransition。Get.generalDialog则可替代showGeneralDialog提供对pageBuilder、transitionBuilder、barrierDismissible等底层参数的完整控制其Navigator取自Get.nestedKey(id)?.navigatorKey或overlayContext的根导航器extension_navigation.dart。3.2 overlayContext 与 context对于所有其他类型的 Dialog Widget包括 Cupertino 系列你可以用Get.overlayContext替代context在代码任意位置打开Get.overlayContextOverlay 级别的 Context位于最顶层extension_navigation.dart适合弹层类 UIGet.context当前路由的 Contextextension_navigation.dart。这两个 Context 在 99% 的场景下都能替代 UI 中的context唯一例外是当InheritedWidget的使用不经过导航 context 时。3.3 Get.bottomSheetGet.bottomSheet()等价于showModalBottomSheet()但同样不需要 context。其实现见 extension_navigation.dart 的ExtensionBottomSheet底层通过GetModalBottomSheetRoute压入导航栈默认enterBottomSheetDuration为 250ms、exitBottomSheetDuration为 200ms。Get.bottomSheet( Container( child: Wrap( children: Widget[ ListTile( leading: Icon(Icons.music_note), title: Text(Música), onTap: () {} ), ListTile( leading: Icon(Icons.videocam), title: Text(Vídeo), onTap: () {}, ), ], ), ), );四、命名路由导航GetMaterialApp 与 GetPage如果你倾向于用字符串名称管理路由GetX 提供完整的命名路由体系。三个核心跳转 APIGet.toNamed(/ProximaTela); // 跳转到新页面 Get.offNamed(/ProximaTela); // 跳转并移除当前页不可返回 Get.offAllNamed(/ProximaTela); // 跳转并清空全部历史路由4.1 用 GetMaterialApp 定义路由表命名路由必须在GetMaterialApp中通过getPages参数注册void main() { runApp( GetMaterialApp( initialRoute: /, getPages: [ GetPage(name: /, page: () Home()), GetPage(name: /login, page: () Login()), GetPage(name: /cadastro, page: () Cadastro(), transition: Transition.cupertino), ] ) ); }GetMaterialApp的完整可选参数见 get_material_app.dart除了标准的theme、locale、routes等 MaterialApp 参数外还扩展了getPages、unknownRoute、routingCallback、defaultTransition、enableLog、popGesture、smartManagement等 GetX 专属配置详见第八节。4.2 GetPage命名路由的配置单元GetPage类定义在 lib/get_navigation/src/routes/get_route.dart每个GetPage代表一条路由核心字段包括字段默认值说明name必填路由名必须以/开头构造器中有 assert 校验page必填返回 Widget 的构建函数transitionnull转场动画类型见下方Transition枚举curveCurves.linear动画曲线opaquetrue路由是否不透明maintainStatetrue离开后是否保持状态binding/bindings/binds空页面级依赖注入middlewares空路由中间件列表parametersnull路由参数fullscreenDialogfalse是否全屏对话框样式children空嵌套子路由popGesturenull是否启用 iOS 侧滑返回GetPage在构造时会调用_nameToRegex(name)把路由名编译为路径匹配规则get_route.dart这是下一节动态 URL 参数得以工作的底层机制。Transition枚举定义在 lib/get_navigation/src/routes/transitions_type.dart共有 17 种可选动画fade、fadeIn、rightToLeft、leftToRight、upToDown、downToUp、rightToLeftWithFade、leftToRightWithFade、zoom、topLevel、noTransition、cupertino、cupertinoDialog、size、circularReveal、native。4.3 unknownRoute处理 404 路由对于未定义的路由例如用户手输错误的 URL可以指定unknownRoute兜底展示void main() { runApp( GetMaterialApp( unknownRoute: GetPage(name: /notfound, page: () UnknownRoutePage()), initialRoute: /, getPages: [ GetPage(name: /, page: () MyHomePage()), GetPage(name: /second, page: () Second()), ], ) ); }五、向命名路由传参arguments 与动态 URL5.1 arguments任意类型的传参arguments参数可以接受任何类型——String、Map、List甚至是类的实例Get.toNamed(/ProximaTela, arguments: Get é o melhor);在目标页面类或 Controller中读取print(Get.arguments); // 值: Get é o melhorGet.arguments的取值链路可从 parse_route.dart 确认它最终来自PageSettings.arguments底层通过RouteDecoder.fromRoute解析 URL 并写入路由的arguments字段parse_route.dart。5.2 动态 URL 链接Query 参数GetX 提供了类似 Web 的动态 URL 能力这对 Web 开发者尤其友好——URL 风格与浏览器地址栏一致Get.offAllNamed(/ProximaTela?devicephoneid354nameEnzo);在目标 controller/bloc/stateful/stateless 中读取print(Get.parameters[id]); // 值: 354 print(Get.parameters[name]); // 值: EnzoGet.parameters的数据来源在 parse_route.dart 的ParseRouteTree.matchRoute中它先用Uri.parse解析路由名收集uri.queryParameters再与路径参数合并后统一写入RouteDecoder.parameters最终通过Get.parameters暴露。5.3 路径参数Path 参数除了?keyvalue查询串GetX 还支持/rota/:param形式的路径参数。定义路由时用冒号声明参数占位符void main() runApp( GetMaterialApp( initialRoute: /, getPages: [ GetPage(name: /, page: () Home()), /// 注意:user 不是一条新路由它只是参数声明。 /// 如果 /segunda 已是一条独立路由请使用 /segunda/user/:user /// 不要写成 /segunda/:user/以免与 /segunda 冲突。 GetPage(name: /segunda/:user, page: () Segunda()), // 接收 ID GetPage(name: /terceira, page: () Terceira(), transition: Transition.cupertino), ] ), );跳转时把实际值拼进 URLGet.toNamed(/segunda/34954);目标页面读取print(Get.parameters[user]); // 值: 34954路径参数与查询参数可以混用Get.toNamed(/profile/34954?flagtrue);print(Get.parameters[user]); // 34954 print(Get.parameters[flag]); // true这正是GetPage构造时_nameToRegex编译出的正则匹配规则([\w%-._~!$()*,;:])捕获参数值在运行期的体现get_route.dart。因此你的 Controller 或 Bloc 可以直接发起命名路由跳转完全不需要context当应用编译为 Web 时这些路由会以真实 URL 形态呈现在地址栏中。六、路由 Middleware监听与拦截导航事件6.1 routingCallback轻量监听如果只是想监听路由变化并触发动作比如广告展示可以直接在GetMaterialApp上配置routingCallbackGetMaterialApp( routingCallback: (route){ if(routing.current /segunda){ openAds(); } } )6.2 GetObserver手动接入 Navigator Observer如果项目没有使用GetMaterialApp可以手动把 Get 的 Observer 挂到原生MaterialApp上void main() { runApp( MaterialApp( onGenerateRoute: Router.generateRoute, initialRoute: /, navigatorKey: Get.key, navigatorObservers: [ GetObserver(MiddleWare.observer), // 关键位置 ], ) ); }创建 MiddleWare 类class MiddleWare { static observer(Routing routing) { /// 你可以同时监听普通路由、snackbars、dialogs 和 bottomsheets 事件。 /// 注意snackbar/dialog/bottomsheet 的弹出也会触发 observer /// 如果只想响应页面跳转需要显式排除这些事件。 if (routing.current /segunda !routing.isSnackbar) { Get.snackbar(Olá, Você está na segunda rota); } else if (routing.current /terceira){ print(última rota chamada); } } }GetObserver是NavigatorObserver的子类定义在 lib/get_navigation/src/routes/observers/route_observer.dart它在didPush、didPop、didRemove等回调中更新Routing状态对象。Routing类route_observer.dart持有current当前路由名、previous上一个路由名、isBottomSheet、isDialog等字段供回调读取判断。结合示例三个页面的完整联动首页弹出 SnackBar → 跳转第二页触发 Middleware → 跳转第三页打印日志 → 返回class Primeira extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( icon: Icon(Icons.add), onPressed: () { Get.snackbar(Oi, eu sou uma snackbar moderna); }, ), title: Text(Primeira rota), ), body: Center( child: ElevatedButton( child: Text(Abrir rota), onPressed: () { Get.toNamed(/segunda); }, ), ), ); } } class Segunda extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( icon: Icon(Icons.add), onPressed: () { Get.snackbar(Oi, eu sou uma snackbar moderna); }, ), title: Text(Segunda rota), ), body: Center( child: ElevatedButton( child: Text(Abrir rota), onPressed: () { Get.toNamed(/terceira); }, ), ), ); } } class Terceira extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(Terceira Rota), ), body: Center( child: ElevatedButton( onPressed: () { Get.back(); }, child: Text(Voltar!), ), ), ); } }6.3 GetMiddleware更强大的路由拦截进阶对于需要拦截/重定向的场景仓库还提供了GetMiddleware抽象类lib/get_navigation/src/routes/route_middleware.dart其执行流程为redirect → onPageCalled → onBindingsStart → onPageBuildStart → onPageBuilt → onPageDispose可用于登录鉴权重定向等场景——example_nav2示例中的 auth_middleware.dart 就是典型参考实现。七、Change Theme一键切换主题原文档特别强调不要在GetMaterialApp之上再包任何 Widget 来更新主题否则可能触发 key 重复的问题。很多人习惯用ThemeProvider之类的方式来切换主题这在 GetX 中完全没必要。7.1 基础切换直接调用Get.changeTheme()Get.changeTheme(ThemeData.light());7.2 深色/浅色一键切换把判断当前是否深色模式与切换主题两个 API 组合放入按钮的onPressed即可Get.changeTheme(Get.isDarkMode ? ThemeData.light() : ThemeData.dark());当前为深色时切换到浅色反之切换到深色。从源码看Get.changeTheme(ThemeData theme)实际调用rootController.setTheme(theme)extension_navigation.dartGet.isDarkMode通过theme.brightness Brightness.dark判断extension_navigation.dart。此外还有Get.changeThemeMode(ThemeMode themeMode)extension_navigation.dart可配合ThemeMode.system使用。若需持久化主题可结合shared_preferences保存主题状态在应用启动时读取并调用Get.changeTheme恢复。八、Get 的全局可选配置可以在进入任何路由之前调用Get.config或直接在GetMaterialApp上配置全局参数。需要说明的是当前源码中Get.config方法已被注释标记为TODO: Deprecatedextension_navigation.dart推荐方式是在GetMaterialApp上直接配置以下是两种写法的对照// 推荐方式在 GetMaterialApp 上直接配置 GetMaterialApp( enableLog: true, defaultTransition: Transition.fade, opaqueRoute: Get.isOpaqueRouteDefault, popGesture: Get.isPopGestureEnable, transitionDuration: Get.defaultDurationTransition, defaultGlobalState: Get.defaultGlobalState, ); // 旧版方式源码中已弃用 Get.config( enableLog true, defaultPopGesture true, defaultTransition Transitions.cupertino )各配置项含义配置项默认值作用enableLogkDebugMode见 get_material_app.dart是否输出 GetX 日志defaultTransition取决于平台全局默认转场动画opaqueRouteGet.isOpaqueRouteDefault路由是否默认不透明见 extension_navigation.dartpopGestureGet.isPopGestureEnable是否默认启用 iOS 边缘侧滑返回transitionDurationGet.defaultDurationTransition全局转场动画时长defaultGlobalStateGet.defaultGlobalState是否启用全局状态九、Nested Navigators按 ID 管理的嵌套导航栈GetX 让 Flutter 的嵌套导航变得简单无需context通过 ID 定位对应的导航栈。注意并行维护多套导航栈可能比较危险。理想情况下应避免使用NestedNavigators或谨慎使用。如果你的项目确实需要比如底部 Tab 各自独立的历史栈可以继续但要注意多套导航栈驻留内存对 RAM 的消耗。用法如下用nestedKey(1)创建一个带索引的GlobalKey作为Navigator的 key跳转时通过id参数指定目标导航栈Navigator( key: nestedKey(1), // 用索引创建 key initialRoute: /, onGenerateRoute: (settings) { if (settings.name /) { return GetPageRoute( page: () Scaffold( appBar: AppBar( title: Text(Principal), ), body: Center( child: TextButton( color: Colors.blue, child: Text(Ir para a segunda), onPressed: () { Get.toNamed(/segunda, id:1); // 通过索引导航到嵌套导航栈 }, ) ), ), ); } else if (settings.name /segunda) { return GetPageRoute( page: () Center( child: Scaffold( appBar: AppBar( title: Text(Principal), ), body: Center( child: Text(Segunda) ), ), ), ); } } ),源码层面Get.nestedKey(String? key)通过rootController.nestedKey(key)获取对应的GetDelegateextension_navigation.dartIGetNavigation中的to、toNamed、off、offAll等方法均支持可选的String? id参数来指定操作哪一套嵌套导航栈见 get_navigation_interface.dart 中各方法签名从而让同一个页面在不同 Tab 栈中各自维护独立的导航历史。结语从无 context 的Get.to到支持动态 URL 的命名路由从 Middleware 监听到嵌套导航栈GetX 的路由体系把 Flutter 导航从处处需要 BuildContext的束缚中解放出来。建议读者在掌握本文 API 后进一步阅读仓库中的配套实现与示例路由核心实现位于 lib/get_navigation/src/routes完整的命名路由 Middleware 项目可参考 example_nav2/lib/app/routes/app_pages.dart 与 example_nav2/lib/app/middleware/auth_middleware.dart单元测试覆盖见 test/navigation/routes_test.dart 与 test/navigation/middleware_test.dart。赞分享前端【免费下载链接】getxOpen screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.项目地址https://gitcode.com/gh_mirrors/ge/getx点击查看免费下载相关推荐GetX 路由管理完全指南无 Context 导航、命名路由、动态 URL 与嵌套导航GetX 路由管理完全指南无 Context 导航、命名路由、动态 URL 与嵌套导航 GetXGet是 Flutter 生态中一套集路由管理、状态管理与前端Zulip AppVeyor Webhook 集成将 Windows CI 构建通知接入 Zulip 的完整指南Zulip AppVeyor Webhook 集成将 Windows CI 构建通知接入 Zulip 的完整指南 导读 AppVeyor 是面向 Window前端GetX 路由管理完全指南无 Context 导航、命名路由、动态 URL 与嵌套导航实战GetX 路由管理完全指南无 Context 导航、命名路由、动态 URL 与嵌套导航实战 本文围绕开源仓库 GetX gh_mirrors/ge/getx前端上一篇【亲测免费】 Jimp 图像处理库教程下一篇Grpclib: 异步Python版gRPC实现的安装与使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表