flutter开发实战-go_router使用

【vue-router源码】八、router.go、router.back、router.forward源码解析 【vue-router源码】系列文章将带你从0开始了解vue-router的具体实现。本篇文章将介绍router。go、router.back、router.forward的实现。 阅读详情
AI摘要

本文深入探讨Flutter第三方插件go_router的使用方法,包括路由配置、跳转、参数传递、子路由、重定向及错误处理等功能,助力开发者轻松实现复杂的导航逻辑。

flutter开发实战-go_router使用

在这里插入图片描述

一、go_router介绍与特性

go_router是一个Flutter的第三方声明式路由插件,使用路由器API提供一个方便的、基于url的API,用于在不同屏幕之间导航。可以定义URL模式、使用URL导航、处理深度链接以及许多其他与导航相关的场景。

GoRouter具有许多功能,使导航变得简单明了:

  • 使用模板语法解析路由路径和路由查询(query)参数;
  • 支持单个目标路由展示多个页面(子路由);
  • 重定向:可以基于应用状态跳转到不同的URL,比如用户没有登录时跳转到登录页;
  • 使用 StatefulShellRoute 可以支持嵌套的 Tab 导航;
  • 同时支持 Material 风格和 Cupertino 风格应用;
  • 兼容 Navigator API 。

二、引入go_router

根据自己需要的版本引入对应的版本,在pubspec.yaml加入

  go_router: ^8.2.0
    

稍后执行flutter pub get命令

三、go_router路由配置

引入插件后,我们需要配置MaterialApp.router的routerConfig

/// The route configuration.
final GoRouter _router = GoRouter(
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomeScreen();
      },
      routes: <RouteBase>[
        GoRoute(
          path: 'details',
          builder: (BuildContext context, GoRouterState state) {
            return const DetailsScreen();
          },
        ),
      ],
    ),
  ],
);
    

配置MaterialApp.router

/// The main app.
class MyApp extends StatelessWidget {
  /// Constructs a [MyApp]
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
    );
  }
}
    

四、go_router路由跳转

如果跳转页面,可以使用content.go

context.go('/details')

4.1、路径参数

GoRouter 的每一个路由都通过 GoRoute对象来配置,可以通过路径参数进行传递相关参数到目标页面。例如路径comment/参数id

GoRoute(
          path: 'comment/:id',
          builder: (BuildContext context, GoRouterState state) {
            String? id = state.pathParameters['id'];
            print("id:${id}");// Get "id" param from URL
            return CommentScreen(id: id);
          },
        ),

那么可以通过context.go(’/comment/55555’)传参数

ElevatedButton(
          onPressed: () => context.go('/comment/55555'),
          child: const Text('Go to the comment screen'),
        )

4.2、路径查询参数

可以获取路径的查询参数 URL 路径中的查询(query)参数,例如从/search?keyword=myname中获取search参数。

GoRoute(
          path: 'search',
          builder: (BuildContext context, GoRouterState state) {
            String? keyword = state.queryParameters['keyword'];
            print("keyword:${keyword}"); // Get "id" param from URL
            return SearchScreen(keyword: keyword);
          },
        ),

传递参数context.go(’/search?keyword=myName’)目标页面可以得到参数myName

ElevatedButton(
              onPressed: () => context.go('/search?keyword=myName'),
              child: const Text('Go to the Search screen'),
            ),

五、添加子路由

子路由,路由匹配支持多个页面,当一个新的页面在旧的页面之上展示时

GoRoute(
          path: 'details',
          builder: (BuildContext context, GoRouterState state) {
            return const DetailsScreen();
          },
          routes: <RouteBase>[
            // Add child routes
            GoRoute(
              path: 'sub-details',
              // NOTE: Don't need to specify "/" character for router’s parents
              builder: (context, state) {
                return SubDetailsScreen();
              },
            ),
          ],
        ),

可以通过context.go(’/details/sub-details’)来进行调用

ElevatedButton(
              onPressed: () => context.go('/details/sub-details'),
              child: const Text('Go to the SubDetails screen'),
            ),

六、页面导航

go_router提供多种方式进行跳转

context.goNamed方式

ElevatedButton(
              onPressed: () => context.goNamed('/details'),
              child: const Text('Go to the Details screen'),
            ),

七、路由重定向

go_router提供全局重定向,比如在没有登录的用户,需要跳转到登录页面.在 GoRouter 中,可以通过redirect 参数配置重定向.

redirect: (BuildContext context, GoRouterState state) {
    final isLogin = false;// your logic to check if user is authenticated
    if (!isLogin) {
      return '/login';
    } else {
      return null; // return "null" to display the intended route without redirecting
    }
  }

八、错误处理(404页面)

go_router为MaterialApp 和CupertinoApp定义了默认的错误页面,也可以通过 errorBuilder 参数自定义错误页面。

errorBuilder: (
    BuildContext context,
    GoRouterState state,
  ) {
    // ErrorPage
    return ErrorScreen();
  }

九、路由跳转监测

在flutter自带的会有NavigatorObserver,go_router页提供路由跳转监测功能

class MyNavigatorObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('did push route');
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('did pop route');
  }
}

在observers中配置

GoRouter(
  observers: [MyNavigatorObserver()],
...
)

这里只是代码尝试了一下常用功能。还有一些转场动画、嵌套导航等等特性需要去尝试。
可以查看https://juejin.cn/post/7270343009790853172

注意:不同版本的代码有所不同。

测试的完整代码如下

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() {
  runApp(const MyApp());
}

class MyNavigatorObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('did push route');
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('did pop route');
  }
}

/// The route configuration.
final GoRouter _router = GoRouter(
  observers: [MyNavigatorObserver()],
  redirect: (BuildContext context, GoRouterState state) {
    final isLogin = false; // your logic to check if user is authenticated
    if (!isLogin) {
      return '/login';
    } else {
      return null; // return "null" to display the intended route without redirecting
    }
  },
  errorBuilder: (
    BuildContext context,
    GoRouterState state,
  ) {
    // ErrorPage
    return ErrorScreen();
  },
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomeScreen();
      },
      routes: <RouteBase>[
        GoRoute(
          path: 'details',
          builder: (BuildContext context, GoRouterState state) {
            return const DetailsScreen();
          },
          routes: <RouteBase>[
            // Add child routes
            GoRoute(
              path: 'sub-details',
              // NOTE: Don't need to specify "/" character for router’s parents
              builder: (context, state) {
                return SubDetailsScreen();
              },
            ),
          ],
        ),
        GoRoute(
          path: 'comment/:id',
          builder: (BuildContext context, GoRouterState state) {
            String? id = state.pathParameters['id'];
            print("id:${id}"); // Get "id" param from URL
            return CommentScreen(id: id);
          },
        ),
        GoRoute(
          path: 'search',
          builder: (BuildContext context, GoRouterState state) {
            String? keyword = state.queryParameters['keyword'];
            print("keyword:${keyword}"); // Get "id" param from URL
            return SearchScreen(keyword: keyword);
          },
        ),
      ],
    ),
  ],
);

/// The main app.
class MyApp extends StatelessWidget {
  /// Constructs a [MyApp]
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
    );
  }
}

/// The home screen
class HomeScreen extends StatelessWidget {
  /// Constructs a [HomeScreen]
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home Screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => context.goNamed('/details'),
              child: const Text('Go to the Details screen'),
            ),
            SizedBox(
              height: 30,
            ),
            ElevatedButton(
              onPressed: () => context.go('/details/sub-details'),
              child: const Text('Go to the SubDetails screen'),
            ),
          ],
        ),
      ),
    );
  }
}

/// The details screen
class DetailsScreen extends StatelessWidget {
  /// Constructs a [DetailsScreen]
  const DetailsScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Details Screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => context.go('/comment/55555'),
              child: const Text('Go to the comment screen'),
            ),
            SizedBox(
              height: 30,
            ),
            ElevatedButton(
              onPressed: () => context.go('/search?keyword=myName'),
              child: const Text('Go to the Search screen'),
            ),
          ],
        ),
      ),
    );
  }
}

/// The details screen
class SubDetailsScreen extends StatelessWidget {
  /// Constructs a [SubDetailsScreen]
  const SubDetailsScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('SubDetailsScreen Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => context.go('/details'),
          child: const Text('Go back to the Details screen'),
        ),
      ),
    );
  }
}

/// The details screen
class CommentScreen extends StatelessWidget {
  /// Constructs a [DetailsScreen]
  const CommentScreen({super.key, this.id});

  final String? id;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('CommentScreen Screen')),
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text("param id:${id}"),
          SizedBox(
            height: 30,
          ),
          ElevatedButton(
            onPressed: () => context.go('/'),
            child: const Text('Go back to the Details screen'),
          ),
        ],
      )),
    );
  }
}

/// The Search screen
class SearchScreen extends StatelessWidget {
  /// Constructs a [DetailsScreen]
  const SearchScreen({super.key, this.keyword});

  final String? keyword;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('SearchScreen Screen')),
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text("param keyword:${keyword}"),
          SizedBox(
            height: 30,
          ),
          ElevatedButton(
            onPressed: () => context.go('/'),
            child: const Text('Go back to the details screen'),
          ),
        ],
      )),
    );
  }
}

/// The Search screen
class ErrorScreen extends StatelessWidget {
  /// Constructs a [DetailsScreen]
  const ErrorScreen();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('ErrorScreen Screen')),
      body: Center(
        child: Container(
          child: const Text('Error info'),
        ),
      ),
    );
  }
}

十、小结

flutter开发实战-go_router使用

学习记录,每天不停进步。

Flutter实战之go_router路由组件入门指南 Flutter go_router组件使用入门指南 阅读详情

相关推荐

Flutter教程之带有 GoRouter 的 Flutter Navigator 2.0,使用 go_router 包了解 Flutter 中的声明式路由机制(教程含源码)

GoRouter是基于Navigation2.0的Flutter应用程序的声明式路由器,用于降低复杂性,无论应用程序运行的平台如何(移动、Web或桌面),处理深度和动态链接以及数据驱动的路由,同时仍提供简单的使用开发人员的经验。Flutter中的Navigator小部件是一种命令式路由机制(Navigator1.0),Navigator2.0是声明式导航的标准参考,不会取代Navigator1.0,因为它们可以一起使用。现在什么是命令式和声明式?......

iCloudEnd的博客 1754

flutter : 一篇文章入门go_router

go_router是Flutter官方开发的一个Flutter的声明式路由包。go_router 包的目的是使用声明式路由来降低复杂性,无论您的目标平台是什么(移动、Web、桌面),处理来自 Android、iOS 和网络的深度和动态链接,以及其他一些导航相关的场景,同时希望提供易于使用的开发人员体验。

卓原的进化之旅 6789

Go-gorouter一个简单高性能的Http路由器

gorouter 一个简单、高性能的Http路由器(支持正则,轻松创建RESTFul API)

Flutter go_router 路由管理全面指南

go_router是一个 Flutter 的第三方路由插件,相比 Flutter 自带的路由,go_router更加灵活,而且简单易用。在 App 应用中,如果你想自己控制路由的定义和管理方式,那么它将十分有用。同时,对于 Web 应用来说,go_router也提供了很好的支持。使用go_router后,你可以定义 URL 的格式,使用 URL 跳转,处理深度链接以及其他一系列的导航相关的应用场景。@override。

yihanss的博客 5983

adams案例分析_案例1(麦弗逊悬架子系统创建)

本文字数3292字83图,建议阅读时间26分钟首先看下案例1的麦弗逊悬架数模结构就不细讲了,从数模上主要是获取硬点坐标(铰接点、安装点、参考点)及大部件结构(副车架、摆臂、转向节等实际运动过程中会产生变形的部件,在ADAMS Car中我们就可以用柔性体来搭建)再来回顾下上一篇讲到的模型元素1、Hardpoint——硬点(只有位置没有方向)2、Parameter Variable——参数...

weixin_39609407的博客 6476

BrainVision Recorder 和 BrainVision Analyzer 2.2 安装

本篇为《EEG处理》系列博客的第二篇,该系列博客主要记录EEG信号处理的学习过程中的软件安装和学习过程,方便以后查阅。本篇为BrainVision Recorder 和 BrainVision Analyzer 2.2 的安装过程。 BrainVision Recorder 和 BrainVision Analyzer 2.2 安装安装前奏Brain Vision Analyzer分析软件 安装Brain Vision Recorder记录软件 安装推荐几款个人使用的科研软件 安装前奏 Brain V

梁小憨憨的博客 5064

vue router.push(),router.replace(),router.go(),router.back(),router. forward()

1、router.push():导航到不同的 url,向 history 栈添加一个新的记录。(=== window.history.pushState) 声明式 编程式 <router-link :to=""> router.push() // 字符串 router.push('home') // 对象 router.push({ path: 'home' })...

LonewoIf的博客 8530

重磅!AI实时读取总结微信聊天记录,附MCP协议+智能体配置教程!

【摘要】本文介绍了一套AI实时分析微信聊天记录的解决方案,通过Chatlog+Trae+MCP协议实现智能整理群聊信息。Chatlog作为开源工具本地解析微信数据,确保隐私安全;Trae提供AI分析能力,支持自然语言处理。操作步骤包括:1)下载运行Chatlog并启动HTTP服务;2)安装Trae配置MCP协议;3)创建智能体设置提示词。该方案虽需初始配置,但能有效解决群聊信息过载问题,自动提炼关键内容,避免有价值信息被淹没。文中提供了详细教程链接和网盘资源。

puyihuan的博客 1万+

router.push(),router.replace(),router.go()

1.router.push(location)=====window.history.pushState 想要导航到不同的 URL,则使用router.push方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。 // 字符串 router.push('home') // 对象 router.push({ path: 'ho...

qq_36437172的博客 665

华为OD机试双机位C卷-水库溃坝填补(Py/Java/C/C++/Js/Go)

华为OD机试(机考)双机位C卷 【水库溃坝填补】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。水库溃坝填补。

qq_45776114的博客 2109

基于STC8G1K08A单片机的PCA捕获外部信号(100~1000HZ)程序实现

基于STC8G1K08A单片机的PCA捕获外部信号(100~1000HZ)程序实现

weixin_74013772的博客 255

router.push、router.replace、router.go的区别?

本文对比了Vue路由中的三种跳转方法:router.push、router.replace和router.go。核心区别在于对浏览器历史记录的操作方式:push会新增记录,允许后退;replace替换当前记录,无法后退;go则基于当前记录前进或后退。文章详细介绍了每种方法的参数格式和使用场景,并对比了Vue2和Vue3的语法差异。最佳实践建议:普通跳转用push,重定向用replace,返回/前进用go,页面刷新推荐使用原生方法而非go(0)。

466

python实现Markowitz模型 (附完整源码)

python实现Markowitz模型 (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 405

router.push(),router.repalce(),router.go()使用

router对象提供了三个用于跳转链接的方法: router.push( ... ) =>跳转到某个子页面,并在history中添加一条记录 router.repalce( ... ) =>替换当前的页面,其实也可以理解为跳转,和push的区别就是不会在history中添加记录 router.go(number) =>刚才提到的history,在go()中被使用,跳转到上一页就...

Songywaa的博客 911

ROS Motion Planning运动规划库安装方法及进阶使用方法详细介绍

​今天偶然发现了一个优质的运动规划库:ai-winter/ros_motion_planning,比较适合从事ROS移动机器人运动规划研究领域的小伙伴学习和使用,相比于莱斯大学Kavraki实验室提供的开源的著名运动规划库OMPL、或着我之前介绍过的zhm-real开源的zhm-real/MotionPlanning和zhm-real/PathPlanning运动规划库,今天介绍的ROS Motion Planning运动规划库与ROS机器人中常用的Navigation导航框架的兼容性更好,库中的运动规划

慕羽★的博客 5578

第78章:PCL Multiple View ICP 多视角配准

多视角配准(Multiple View ICP)是迭代最近点(ICP)算法的扩展,旨在处理多视角的点云数据配准问题。传统的ICP算法主要用于两幅点云之间的配准,而多视角配准则处理来自多个视角或不同时间采集的多个点云数据的配准任务。在实际应用中,多个传感器或多个拍摄角度获得的点云数据常常需要进行联合配准。这些点云可能由于不同的视角、拍摄位置或时间差异而存在位置和旋转的差异。多视角配准的目标是根据多个点云之间的匹配关系,找到它们的相对变换,使得这些点云能够合并成一个统一的三维模型。

yumeiguo的博客 158

Flutter 中使用 go_router

go_router是一个功能强大且灵活的路由管理库,支持路由参数、嵌套路由、重定向和导航守卫等功能,使得在复杂应用中进行路由管理变得更加简洁和清晰。

weixin_42766526的博客 1985

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

vue 中router.go;router.push和router.replace的区别

router.go(n) 这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n) router.push(location) 想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。 router.repla...

div_ma的博客 2万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【Flutter】- go_router路由

go_router是一个 Flutter 的第三方路由插件,相比 Flutter 自带的路由,go_router 更加灵活,而且简单易用。在 App 应用中,如果你想自己控制路由的定义和管理方式,那么它将十分有用。同时,对于 Web 应用来说,go_router 也提供了很好的支持。使用 go_router 后,你可以定义 URL 的格式,使用 URL 跳转,处理深度链接以及其他一系列的导航相关的应用场景。使用模板语法解析路由路径和路由查询(query)参数;支持单个目标路由展示多个页面(子路由);

不靠谱先森的博客 1411

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

vue router.push(),router.replace(),router.go()和router.replace后需要返回两次的问题

转载:https://www.cnblogs.com/lwwen/p/7245083.html    https://blog.youkuaiyun.com/qq_15385627/article/details/83146766 1.router.push(location)=====window.history.pushState 想要导航到不同的 URL,则使用router.push...

weixin_30709061的博客 765

vue router.push(),router.replace(),router.go()

1.router.push(location)=====window.history.pushState 想要导航到不同的 URL,则使用 router.push方法。这个方法会向 history...

qq_36320160的博客 428

flutter 解决go_router和smartdialog 初始化冲突的问题

flutter 解决go_router和smartdialog 初始化冲突的问题

瞬神_夜一的专栏 1571

【Flutter】Navigator与go_router

路由之间的跳转是任何前端开发绕不开的话题! 2.动态路由 Navigator 静态路由页面跳转传递参数: onGenerateRoute 可以通过onGenerateRoute控制路由页面跳转的权限,比如哪些页面需要登陆之后才能查看和查阅的,就可以在onGenerateRoute里面进行处理,避免在每个page 的页面里面进行判断处理,路由拦截的功能 三.go_router go_router是flutter.dev 官方推出的路由管理插件,非内置,有需要导入 例子: 路由之间传递参数 1.没

自动人生博客 2360

vue router.push(),router.replace(),router.go()

1.router.push(location)=====window.history.pushState 想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。 // 字符串 router.push('home') // 对象 router.push({ path: 'ho...

_夜渐凉 444

vue路由导航方法 router.push,router.replace,router.go,router.back,router. forward

方法 说明 router.push(url) 导航到新url,向 history栈添加一条新访问记录,等同于window.history.pushState router.replace(url) 导航到新url,替换 history 栈中当前记录,等同于window.history.replaceState router.go(num) 导航到指定步数的记录,num为正数是前进,为负数是后退,为0的时候是刷新当前页面,等同于window.histo...

lihefei_coder的博客 2978
上一篇: flutter开发实战-AssetBundle读取指定packagename的文件
下一篇: flutter开发实战-dio Interceptor统一设置ua及接口参数
BruceGwo
博客等级 码龄16年 549粉丝 278原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值