首页 > 三国杂项 > 正文

1. 普通路由

普通路由传递参数很简单,就是自定义的Widget其实就是一个类, 定义Widget时,构造函数接收参数,然后跳转到这个Widget时,和普通的类一样传递参数就好了。

1.1 简单实例

// 自定义一个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)
    );
  }
}
// 外部跳转到自定义的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. 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传值和接收

// 这里的代码并不是完整的 只是关键的代码部分 用于理解和复习
// 跳转时 使用
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.此处仅设置路由 关于跳转 在后面一点

2.1.1 home属性

用于定义页面显示的内容,优先级最高。

MaterialApp(
      title: "路由管理",
      home:Scaffold(
		appBar: AppBar(title: Text("主页"),),
		body:Container(child:Text('主页的内容'))
	  ),
)

2.1.2 routes 路由管理 设置了之后就可以使用Navigator跳转了

// 默认进入页面时,路由为'/',此时会跳转到'/'对应的页面,即'/'对应的就是初始页面 和home基本等效

// 因此 当设置了home之后 routes不可以设置'/'路由。

// 作用是 进行路由的分发,当Navigator进行跳转的时候,根据此Map进行跳转

// 接收一个Map<String ,Widget Function(BuildContext)> 即接收一个Map,键是字符串value是一个返回值为Widget类型的函数 

// 函数接收一个BuildContext类型的参数context 

// 传递参数的方式和普通路由是一样的 通过类的构造函数进行传递
MaterialApp(
    title: "路由管理",
    // 这里是设置路由,跳转后面会说
    routes:{
		'/':()=>Home(),  // 初始页面 Home就是这个页面显示的内容 当和home同时设置时 会报错
		'/login':()=>Login(), // 当使用Navigator跳转时使用
	}
)

2.1.3 onGenerateInitialRoutes 生成初始化路由

// 这个类似于home,接收多个Route,依次push,作为本页面的初始页面,效果和home基本一致 
// 不得和home一起使用 否则报错 用法简单  尝试一下 马上就懂
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 路由管理拦截器

// 在路由跳转时,接收路由的配置,并可以进行操作
// 因此 除了可以使用routes进行路由的配置,也可以使用onGenerateRoute管理路由
// 可以和home属性和routes属性一起设置 但是优先级最低  因此冲突的时候 显示的是home属性或者routes属性设置的页面
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 路由不存在时跳转的页面

这里的代码不是完整的哦~

MaterialApp(
    title: "路由管理",
    onUnknownRoute: (RouteSettings settings){
  		return MaterialPageRoute(builder: (context){
    		return Scaffold(appBar: AppBar(title: Text("404 not fouond"),),);
  });
},
)
// 总结的说就是:
// 1.都可以设置初始的页面
// 2.routes和onGenerateRoute 有分发路由的功能
// 3.home和onGenerateInitialRoutes 仅仅只能设置初始页面
// 4.home和routes和onGenerateInitialRoutes存在同时设置初始页面会报错的情况

2.2 命令路由传值和接收

2.2.1 命令路由跳转和传递参数

// 带Named的是命令路由跳转,不带的就是普通路由跳转
// 接收 接收三个参数(context,route,arguments) route是字符串 即routes或onGenerateRoute中设置的  
// 如果跳转到一个不存在的路由 就会进入onUnknownRoute设置的页面
// 其他的方式使用基本差不多 较为简单 这里不做赘述
// arguments为命名参数 即可传可不传 根据需求决定
Navigator.pushNamed(context,'/login',arguments: 'arguments');

2.2.2 命令路由接收参数

在Widget类的build函数中接收参数

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方式接收参数

MaterialApp(
    title: "路由管理",
    onGenerateRoute:(RouteSettings settings){
        // 这里的arguments就是传递过来的参数
        // 可以根据自己的需求进行传递或者别的操作
        print(settings.arguments);
        return  MaterialPageRoute(builder: (context){
          // 传递参数 直接传递给Widget类的构造函数
  		  // Home中需要对参数进行接收
          return Home(arguments:settings.arguments);
        });
      }
    },
)
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. 路由模块化

// 可以根据自身的情况,将路由的管理抽离,放到单独的一个文件,并对路由进行统一的处理
// routes直接进行抽离即可 onGenerateRoute需要进行一些封装

将onGenerateRoute进行模块化

// 这里进行路由的配置
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("路由不存在"),),);
    });
  }
}
将路由抽离出去作为单独的一个模块,有助于项目的管理,还有很多用法可以探索一下。

版权声明:部分文章、图片等内容为用户发布或互联网整理而来,仅供学习参考。如有侵犯您的版权,请联系我们,将立刻删除。

猜你喜欢
发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论信息