futter-路由和导航

187 阅读3分钟

前言

flutter开发过程中一定会用到导航,即:跳转页面跳回页面.

这一章就主要介绍路由导航以及导航传值的问题

demo地址(内容在router文件夹中,可以替换main中注释尝试效果)

路由Route和导航Navigator

一个Route是一个屏幕或页面的抽象,Navigator 是管理route的Widget,最常见功能pushpop页面

注意: 当前页面A 跳转 页面B 的前提是,A页面得有导航,否则会报错

push

默认可以使用 Navigator.push来跳转到指定页面,需要使用 MaterialPageRoute包装跳转的页面,如下所示

//默认push
Navigator.push(context, 
    MaterialPageRoute(builder: (BuildContext context) => const RouterPage1()));
//先调用 of 在调用 push,这个of返回的 NavigatorState 可以
Navigator.of(context).push( 
    MaterialPageRoute(builder: (BuildContext context) => const RouterPage1()));

//push到某个页面的时候,由于调用的构造方法,可以通过构造方法传参到指定页面
Navigator.push(context, 
    MaterialPageRoute(builder: (BuildContext context) => const RouterPage1("我是传递的数据")));

push的同时,接收pop返回的参数,由于push方法是一个 Future,可以通过 await 或者 .then方法来获取(await的前提是,此函数是 async 修饰的异步支持函数)

Navigator
    .push(context, 
        MaterialPageRoute(builder: (context) => const RouterPage1("我是首页传递的数据")))
    .then((value) {
  log("我是第一页反向传递过来的value");
  print(value);
});

扩展push

由于 dart 不能扩展静态方法(静态方法只能通过对应的类名调用,扩展也要通过扩展的类名,看起来很怪),所以我们直接扩展 Navigator.of 返回的 NavigatorState 即可

另外如果要扩展另一种动画的 push, 可以可以写完,在这里面在

extension ExtendNavigator on NavigatorState {
  Future pushWidget(Widget widget) {
    return push(MaterialPageRoute(builder: (context) => widget));
  }

  //如果想设置特殊的push动画也可以,也可以在这里面写
}

//调用逻辑
Navigator.of(context).pushWidget(const HomePage());

pop

默认可以使用 Navigator.pop直接跳会上一个页面

//跳转上一个页面
Navigator.pop(context);

//跳转上一个页面同时,传递参数过去
Navigator.pop(context, '我是第一页传递回去的内容');

主动 pop 时,需要注意,在有延迟的操作后执行pop操作时,最后提前判断一下当前页面是是否还存在,否则可能会引起错误

//当前页面还存在的情况在进行pop
if (mounted) {
  Navigator.of(context).pop();
}

配置路由名,通过路由名导航

如下所示,在 MaterialApp中设置 routes 路由参数

MaterialApp(
  title: "flutter router",
  //如果不用名字跳转的话,这一个不用声明
  routes: {
    'RouterPage1': (BuildContext context) => const RouterPage1(),
    'RouterPage2': (BuildContext context) => const RouterPage2(),
    'HomePage': (BuildContext context) => const HomeRouterPage(),
  },
  initialRoute: "HomePage", //设置首页路由,设置了 home 就不用填写了
  //home: const HomeRouterPage(),
);

这样就可以通过名字 push

用路由名字push

通过,设定的路由名字 namepush

//通过name push,看起来更适合跳转固定设置好的界面
Navigator.pushNamed(context, "RouterPage1");

//和上面一样
Navigator.of(context).pushNamed("routeName");

ps: routes方式使用起来看起来更加简洁,比较符合react技术栈的风格,但也出现了另外一个问题,就是跳转时构造方法有参数的情况,仍然需需要使用默认的push,否则会出现一系列问题,还有就是特殊页面的不同切换动画问题

替换跟路由

除了直接push、pop还有替换跟路由的,一般是启动页切换正常页面时会用到,因此也没有push默认的返回按钮了

Navigator.of(context).pushReplacementNamed("路由名字"); //替换根路由

最后

路由routes和默认 push 各有各的优点,可以根据情况灵活使用,当然如果嫌两种麻烦的话,最好是直接使用push,稍微自定义一下即可

案例代码很详细,如果想仔细看的话,可以看代码,代码就在 lib/router 文件夹中,快去尝试一下吧