讲解Flutter 路由传递,这是一个大的概述图。
当 app 的页面变多的时候,就需要考虑页面传值的问题,在第一个页面如何把数据传递到 另外一个页面?最最基本的方法是在打开新页面,传递参数过去。但当 app 变得很大或者功能变多,你会发现传值是一件费劲的事情。例如前期设计的时候,只需要一个参数,但后面发现业务可能需要三个参数,如果再追加两个参数也不是不可以,就是不太优雅,而且可能要修改很多地方。
先简单解释一下,下面会使用到, App 启动一个主界面,然后点击中间按钮,会打开第二个界面。点击第二个界面的右上角,会返回到之前的界面。具体代码如下:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class Test extends StatefulWidget {
@override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('路由'),
),
body: Center(
child: FloatingActionButton(
shape: BeveledRectangleBorder(),
child: Text('按钮'),
onPressed: () {
//使用路由打开 第二个界面
Navigator.push(
context, MaterialPageRoute(builder: (context) => TwoPage()));
},
),
),
);
}
}
class TwoPage extends StatefulWidget {
@override
_TwoPageState createState() => _TwoPageState();
}
class _TwoPageState extends State<TwoPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('第二页'),
),
body: Column(
children: <Widget>[
SizedBox(height: 100),
Text('传递过来的值:\n'),
SizedBox(height: 100),
Center(
child: FloatingActionButton(
shape: BeveledRectangleBorder(),
child: Text('返回'),
onPressed: () {
// 返回到上一个界面
Navigator.pop(context);
},
),
)
],
),
);
}
}
使用构造参数把参数传递过去,在 TwoPage 中接受参数可直接用 widget.x , x 表示 _TwoPageState 传递过来的 widget 中包含值。
class _TestState extends State<Test> {
...
onPressed: () {
String name = "Wang";
String age = "99";
Navigator.push(context, MaterialPageRoute(builder: (context) => TwoPage(name, age)));
},
...
}
class TwoPage extends StatefulWidget {
String name;
String age;
TwoPage(this.name, this.age);
...
Text('传递过来的值:\n ${widget.name}_${widget.age}'),
...
}
这里演示了 使用构造传递一个 List 类型的数, 使用 widget.data 的列表脚本获取数据。
class _TestState extends State<Test> {
...
dynamic data = ['name1', 'age'];
Navigator.push(context, MaterialPageRoute(builder: (context) => TwoPage(data)));
...
}
class TwoPage extends StatefulWidget {
...
dynamic data;
TwoPage(this.data);
...
}
class _TwoPageState extends State<TwoPage> {
...
Text('传递过来的值:\n ${widget.data[0]}_${widget.data[1]}'),
...
}
这里演示了 使用构造传递一个 map 类型的数据。
class _TestState extends State<Test> {
...
dynamic map = {
'name': "Wang_Map",
'age': "99",
};
Navigator.push(context, MaterialPageRoute(builder: (context) => TwoPage(map)));
...
}
class TwoPage extends StatefulWidget {
...
dynamic map;
TwoPage(this.map);
...
}
class _TwoPageState extends State<TwoPage> {
...
Text('传递过来的值:\n ${widget.map["name"]}_${widget.map["age"]}'),
...
}
很多时候我们项目比较大,为了统一管理,会使用带名字的路由概念,下面的路由字符串常量可以写成变量,这样后期不管怎么修改里面的值,依赖的地方都是不需要修改的。
这里传递了一个 name 值,演示了一下 使用带名字的路由传递值。
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: "/",
routes: {
"/": (context) => OnePage(),
"/TwoPage": (context) => TwoPage(),
},
);
}
}
class OnePage extends StatefulWidget {
@override
_OnePageState createState() => _OnePageState();
}
class _OnePageState extends State<OnePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('路由页面'),
),
body: Center(
child: FloatingActionButton(
shape: BeveledRectangleBorder(),
child: Text('按钮'),
onPressed: () {
String name = "Wang";
Navigator.pushNamed(context, '/TwoPage', arguments: name);
},
),
),
);
}
}
class TwoPage extends StatefulWidget {
@override
_TwoPageState createState() => _TwoPageState();
}
class _TwoPageState extends State<TwoPage> {
@override
Widget build(BuildContext context) {
dynamic name = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text('第二页'),
),
body: Column(
children: <Widget>[
SizedBox(height: 100),
Text('传递过来的值:\n $name'),
SizedBox(height: 100),
Center(
child: FloatingActionButton(
shape: BeveledRectangleBorder(),
child: Text('返回'),
onPressed: () {
Navigator.pop(context);
},
),
)
],
),
);
}
}
我们这里传递的是 List,可以根据角标进行获取对应值,前提是对值了解,一般这里会传递一个列表展示或者一个 List 包含多个不同的值,方便从上一次获取。
class _OnePageState extends State<OnePage> {
...
onPressed: () {
dynamic listData = ['name1', 'age'];
Navigator.pushNamed(context, '/TwoPage', arguments: listData);
}
...
}
class _TwoPageState extends State<TwoPage> {
@override
Widget build(BuildContext context) {
dynamic listData = ModalRoute.of(context).settings.arguments;
String name = listData[0];
String age = listData[1];
...
SizedBox(height: 100),
Text('传递过来的值:\n $name _ $age'),
SizedBox(height: 100),
...
}
}
因为我们传递的是 map,所以在接收的时候需要做一次判断,用 is 判断,预防外界传入其他类型,造成我们程序红屏。这里可以从上一次获取多个不同的参数,使用不同名称获取,这里最好对接收到的值做判断,非空校验等。
class _OnePageState extends State<OnePage> {
...
onPressed: () {
dynamic listData = ['name1', 'age'];
Navigator.pushNamed(context, '/TwoPage', arguments: listData);
}
...
}
class _TwoPageState extends State<TwoPage> {
@override
Widget build(BuildContext context) {
String name;
String age;
dynamic mapData = ModalRoute.of(context).settings.arguments;
// 可以做一次校验数据安全,防止类型不匹配
if (mapData is Map) {
Map data = mapData;
name = data['name'];
age = data['age'];
}
...
SizedBox(height: 100),
Text('传递过来的值:\n $name _ $age'),
SizedBox(height: 100),
...
}
}
和带路由名字的方式基本一样,不过写的方式略有不同,需要把参数放入 settings 后面。
Navigator.of(context).push(new MaterialPageRoute(
builder: (context) {
return NewRouteWidget(); //写上要跳转到的页面
},
settings:
RouteSettings(arguments: {'name': 'postbird'}), // 传参
fullscreenDialog: true));
返回上一级:
Navigator.pop(context);
带参数返回上一级:
Navigator.pop(context, '返回的文本数据');
带类型的参数返回:
Navigator.pop<Map>(context, mapData);
Navigator.pop<List>(context, listData);
Navigator.pop<T>(context, data);
在上一级接受返回的值:
这里使用 then 接受,也可以使用 await, 只是这种方法更容易理解和接受,逻辑更强,代码简洁。
Navigator.pushNamed(context, '/TwoPage', arguments: mapData)
.then((dynamic data) {
print("返回的值是:$data");
});
原文:http://gdky005.com/2019/09/10/Flutter-如何在切换页面的时候,把参数传到下一个页面/
在使用vue-cli搭建的环境中,浏览器上URL地址中是存在#的,这是由于vue-router 默认 hash 模式,不难发现#的出现真的很丑陋。官网给出了如何使用history模式mode: history
vue中路由传参主要的3种方式:query方式(push时使用path来匹配)、params模式(push时使用name来匹配)、location预声明参数模式(push使用path来匹配,但是它跟params模式不同)
我们的通用的后台管理系统中,我们会根据权限的粗细不同,会对每个角色每个权限每个资源进行控制。同样的我们也需要实现一个这样的功能。 这篇文章我将主要讲vue端的实现,关于后台接口我就不会涉及,当我接触的时候我们的后台接口是springcloud实现。
前后端分离开发模式,后端会把路由控制丢在前端,这几天再开发单页面小的项目,手动撸了个路由。前端路由实现有两种方法。HTML5 History API包括2个方法:history.pushState()和history.replaceState(),和1个事件:window.onpopstate。hash + location.onhashchange
在后台管理系统中,一般都会采用权限管理。路由菜单数据都会保存到数据库中,在vue-router 2.2版本新增了一个router.addRoutes(routes)方法,即可用它来实现动态路由了
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
原本想用动态路由的思路去做,按权限加载对应路由表,但是由于权限可以交叉(比如一个人可以同时是主题管理员和数据服务管理员),导致权限路由表还是得去做判断组合。于是放弃了这个思路,索性就在beforeEach里直接判断了。
使用vue-cli构建项目后,我们会在Router文件夹下面的index.js里面引入相关的路由组件,webpack在打包的时候会把整个路由打包成一个js文件,如果页面一多,会导致这个文件非常大,加载缓慢
query和params的区别,query相当于get请求,在页面跳转的时候,可以在地址栏看到请求参数,然而params则相当于post请求,参数不会在地址栏中显示。
当服务端接收到HTTP请求时,可以通过onRequest() 获取到url, pathname,query,及paramParams参数;为了解析这些数据需要使用url和querystring模块
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!