1. 普通路由
1 2 | 普通路由传递参数很简单,就是自定义的Widget其实就是一个类, 定义Widget时,构造函数接收参数,然后跳转到这个Widget时,和普通的类一样传递参数就好了。 |
1.1 简单实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // 自定义一个Widget import 'package:flutter/material.dart'; class Home extends StatefulWidget { // 这里的data将有外部传入 这是普通路由传值的方式 String data; Home(this.data); @override _HomeState createState() => _HomeState(); } class _HomeState extends State<Home> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Home"),), // state中可以通过widget获取widget对象 body: Text(widget.data) ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // 外部跳转到自定义的Widgte import 'package:FlutterTest/home.dart'; import 'package:flutter/material.dart'; // home>onInitRoute>onGenerateRoute> main(List<String> args) { runApp(MaterialApp( title: "路由管理", home:Scaffold( appBar: AppBar(title: Text("主页"),), // 此处是因为上文没有context,但是Navigator跳转时需要传入context,因此使用Builder,Builder可以获取到context,具体用法可百度。 body: Builder(builder: (context){ // 按钮 return FlatButton(onPressed: (){ // 这个的写法比较固定,第一个参数接收context,第二个参数接收一个Route,这里使用MaterialPageRoute,return要跳转的页面即可。可以传递参数,如下所示 Navigator.push(context,MaterialPageRoute(builder: (context){ // 返回自定义的Widget并传递参数 return Home('Rob'); })); }, child: Text("跳转到登录页面")); }) ), |
1.2 普通路由常用的Navigator方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 1. Navigator.push(context,route) 跳转至某个页面 可以使用pop回到原页面 Navigator.push(context,MaterialPageRoute(builder: (context){ // 返回一个Widget 跳转也是跳转到这个Widget去 return Home('Rob'); })); // 2. Navigator.pushReplacement(context, newRoute) 跳转并替换当前页面,即跳转后无法返回原页面 // 3. Navigator.pushAndRemoveUntil(context,newRoute,bool Function(route)) 跳转页面 直到参数返回第三个参数时 删除原页面 // 跳转到指定页面,当第三个参数返回值为false时,移除原来的页面,即无法返回,若返回值为true,则可以返回。 // 可以理解为 当返回false时 等效于pushReplacement,返回true时 等效于push // 4. Navigator.pop(context,data) 返回上一个页面 // 5. Navigator.maybePop(context).then((value) => print(value)); // 当可以返回上一个页面时 value为true,然后返回,不能返回时,value为false,不返回 // 6. Navigator.canPop(context) 布尔值 true则可以返回,false不能返回 |
1.3 pop传值和接收
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 这里的代码并不是完整的 只是关键的代码部分 用于理解和复习 // 跳转时 使用 FlatButton(onPressed: ()async{ // 因为pop传值是异步的 因此需要使用await和async接收 跳转后,在使用pop回来时 这里就会接收到传递的数据了 // 接收后一个页面pop过来的数据 var data=await Navigator.push(context,MaterialPageRoute(builder: (context){ return Home('Rob'); })); },child:Text('跳转到Home页面')); // 返回上一个页面并传递参数 FlatButton(onPressed: (){ Navigator.pop(context,'要传递给上一个页面的数据'); },child: Text("返回")) |
2. 命名路由
2.1 MaterialApp路由和页面相关
1 2 | // 1.记住:默认进入页面时 路由为'/' // 2.此处仅设置路由 关于跳转 在后面一点 |
2.1.1 home属性
1 | 用于定义页面显示的内容,优先级最高。 |
1 2 3 4 5 6 7 | MaterialApp( title: "路由管理", home:Scaffold( appBar: AppBar(title: Text("主页"),), body:Container(child:Text('主页的内容')) ), ) |
2.1.2 routes 路由管理 设置了之后就可以使用Navigator跳转了
1 2 3 4 5 6 7 8 9 10 11 | // 默认进入页面时,路由为'/',此时会跳转到'/'对应的页面,即'/'对应的就是初始页面 和home基本等效 // 因此 当设置了home之后 routes不可以设置'/'路由。 // 作用是 进行路由的分发,当Navigator进行跳转的时候,根据此Map进行跳转 // 接收一个Map<String ,Widget Function(BuildContext)> 即接收一个Map,键是字符串value是一个返回值为Widget类型的函数 // 函数接收一个BuildContext类型的参数context // 传递参数的方式和普通路由是一样的 通过类的构造函数进行传递 |
1 2 3 4 5 6 7 8 | MaterialApp( title: "路由管理", // 这里是设置路由,跳转后面会说 routes:{ '/':()=>Home(), // 初始页面 Home就是这个页面显示的内容 当和home同时设置时 会报错 '/login':()=>Login(), // 当使用Navigator跳转时使用 } ) |
2.1.3 onGenerateInitialRoutes 生成初始化路由
1 2 | // 这个类似于home,接收多个Route,依次push,作为本页面的初始页面,效果和home基本一致 // 不得和home一起使用 否则报错 用法简单 尝试一下 马上就懂 |
1 2 3 4 5 6 7 8 9 10 11 12 13 | MaterialApp( title: "路由管理", onGenerateInitialRoutes: (settings){ return [ MaterialPageRoute(builder: (context){ return Scaffold(appBar: AppBar(title: Text("初始化页面1"),)); }), MaterialPageRoute(builder: (context){ return Scaffold(appBar: AppBar(title: Text("初始化页面2"),)); }), ]; }, ) |
2.1.4 onGenerateRoute 路由管理拦截器
1 2 3 | // 在路由跳转时,接收路由的配置,并可以进行操作 // 因此 除了可以使用routes进行路由的配置,也可以使用onGenerateRoute管理路由 // 可以和home属性和routes属性一起设置 但是优先级最低 因此冲突的时候 显示的是home属性或者routes属性设置的页面 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | MaterialApp( title: "路由管理", onGenerateRoute:(RouteSettings settings){ // settings中主要有name和arguments // settings.name是路由名称 print(settings); // 根据不同的路由 进行不同的操作 默认进入时路由为'/' // 当路由为'/login' 时跳转 以此类推 if(settings.name=='/login'){ return MaterialPageRoute(builder: (context){ // settings.arguments是传递的参数 这里接收到之后 再通过类的构造函数的方式 将arguments传递给页面 // 通过构造函数的方式进行传递 return Login(settings.arguments); }); }else{ return MaterialPageRoute(builder: (context){ return Scaffold( appBar: AppBar(title:Text("主页"),), body: Container( child: Text('主页的内容') ), ); }); } }, ) |
2.1.5 onUnknownRoute 路由不存在时跳转的页面
1 | 这里的代码不是完整的哦~ |
1 2 3 4 5 6 7 8 | MaterialApp( title: "路由管理", onUnknownRoute: (RouteSettings settings){ return MaterialPageRoute(builder: (context){ return Scaffold(appBar: AppBar(title: Text("404 not fouond"),),); }); }, ) |
1 2 3 4 5 | // 总结的说就是: // 1.都可以设置初始的页面 // 2.routes和onGenerateRoute 有分发路由的功能 // 3.home和onGenerateInitialRoutes 仅仅只能设置初始页面 // 4.home和routes和onGenerateInitialRoutes存在同时设置初始页面会报错的情况 |
2.2 命令路由传值和接收
2.2.1 命令路由跳转和传递参数
1 2 3 4 5 6 | // 带Named的是命令路由跳转,不带的就是普通路由跳转 // 接收 接收三个参数(context,route,arguments) route是字符串 即routes或onGenerateRoute中设置的 // 如果跳转到一个不存在的路由 就会进入onUnknownRoute设置的页面 // 其他的方式使用基本差不多 较为简单 这里不做赘述 // arguments为命名参数 即可传可不传 根据需求决定 Navigator.pushNamed(context,'/login',arguments: 'arguments'); |
2.2.2 命令路由接收参数
在Widget类的build函数中接收参数
1 2 3 4 5 6 7 8 9 10 11 12 | class Home extends StatelessWidget { @override Widget build(BuildContext context) { print(ModalRoute.of(context).settings.arguments); return Scaffold( appBar: AppBar(title: Text("Home"),), body: Container( child: Text("在build中接收Navigator.pushNamed传递的arguments"), ) ); } } |
onGenerateRoute方式接收参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | MaterialApp( title: "路由管理", onGenerateRoute:(RouteSettings settings){ // 这里的arguments就是传递过来的参数 // 可以根据自己的需求进行传递或者别的操作 print(settings.arguments); return MaterialPageRoute(builder: (context){ // 传递参数 直接传递给Widget类的构造函数 // Home中需要对参数进行接收 return Home(arguments:settings.arguments); }); } }, ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Home extends StatelessWidget { // 定义实例变量进行接收 var arguments; // 构造函数的命名参数 可传可不传 Home({this.arguments}); @override Widget build(BuildContext context) { print(ModalRoute.of(context).settings.arguments); return Scaffold( appBar: AppBar(title: Text("Home"),), body: Container( child: Text("使用构造函数传值的方式接收Navigator传递的arguments"), ) ); } } |
3. 路由模块化
1 2 | // 可以根据自身的情况,将路由的管理抽离,放到单独的一个文件,并对路由进行统一的处理 // routes直接进行抽离即可 onGenerateRoute需要进行一些封装 |
IT营大地老师 我也是看了这个视频之后再去找别的材料 然后进行学习和总结 值得一看
将onGenerateRoute进行模块化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // 这里进行路由的配置 final routes={ '/':(BuildContext context,{arguments})=>Home(''), '/login':(BuildContext context,{arguments})=>Login(arguments:arguments), }; // 这里的代码其实就是将onGenerateRoute抽离出来放到一个单独的文件并进行条件的判断 // 再将其中的函数放到一个Map进行分发 Route<dynamic> onGenerateRoute(RouteSettings settings){ print(settings.name); // 路由名称 final String name=settings.name; // 根据路由名称在routes中找到对应的路由 final Function pageContentBuilder=routes[name]; // 如果路由不为null 即路由存在于routes中 if(pageContentBuilder!=null){ // 如果有接收到arguments if(settings.arguments!=null){ return MaterialPageRoute( builder: (context){ return pageContentBuilder(context,arguments:settings.arguments); } ); }else{ return MaterialPageRoute( builder: (context){ return pageContentBuilder(context); } ); } }else{ return MaterialPageRoute(builder: (context){ return Scaffold( appBar: AppBar(title: Text("404 not found ! !"),), body: Container(child: Text("路由不存在"),),); }); } } |
1 | 将路由抽离出去作为单独的一个模块,有助于项目的管理,还有很多用法可以探索一下。 |