Flutter中封装Fluro路由配置,以及无context跳转与传参

fluro路由简单配置

  • 引入fluro

pubspec.yaml

yml 复制代码
dependencies:
	# 路由管理
  fluro: ^2.0.5

一、封装fluro路由

  • 主要初始化路由表信息,以及找不到页面时默认返回404页面

lib/router/routes.dart

dart 复制代码
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/pages/home/router/router_test_page.dart';
import 'package:planx_app/pages/index_page.dart';
import 'package:planx_app/widget/empty.dart';

class Routes {
  static FluroRouter router = FluroRouter();
  // 设置页面
  // 页面信息
  static String indexPage = "/";
  // 路由测试页面
  static String routerPage = "/routerTest";

  // 初始化,配置路由表
  static _initRouter() {
    // 首页
    router.define(indexPage,
        handler: Handler(handlerFunc: (_, __) => const IndexPage()));
    // 路由测试页面
    router.define(routerPage,
        handler: Handler(handlerFunc: (_, __) => const RouterTestPage()));
  }

  // 配置路由
  static void configureRoutes() {
    router.notFoundHandler = Handler(handlerFunc: (_, __) {
      // 找不到路由时,返回404页面
      return Scaffold(
          appBar: AppBar(),
          // 这是自行封装的Empty组件
          body: const Center(child: Empty(type: EmptyType.page404)));
    });
    // 初始化路由信息
    _initRouter();
  }
}

main.dart 中初始化与配置路由

dart 复制代码
import 'package:planx_app/router/routes.dart';

void main() async {
	// ...
  // 注册路由
  Routes.configureRoutes();
  runApp(const MyApp());
}
// ....
// MaterialApp中配置路由
MaterialApp(
  // ...
  // 配置路由
  onGenerateRoute: Routes.router.generator,
);

二、封装页面跳转的方法

  • flutter中可以直接使用Navigator进行路由调整,为了统一建议还是先封装一下
  • 这里只是简单的封装,在后面还有介绍关于无context跳转,以及特殊参数传递的封装

lib/router/navigator_util.dart

dart 复制代码
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/router/routes.dart';

class NavigatorUtil {
  static void push(
    BuildContext context,
    String path, {
    bool replace = false, // 替换当前页面
    bool clearStack = false,  // 是否清空路由栈
    Object? arguments,
    TransitionType? transition,  // 页面进入动效
  }) {
    Routes.router.navigateTo(
      context,
      path,
      replace: replace,
      clearStack: clearStack,
      // 页面进入从右侧进入
      transition: transition ?? TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }
}

使用

dart 复制代码
 ElevatedButton(
  onPressed: () {
    NavigatorUtil.push(context, Routes.routerPage);
  },
  child: const Text("跳转路由测试页面"),
),

效果:

无context跳转

有些时候我们可能不会在builder中跳转路由,所以没有context

  • 在MaterialApp中有一个navigatorKey属性,指定navigatorKey后就可以直接操作Navigator,不需要使用context

重新封装路由跳转方法

lib/router/navigator_util.dart

dart 复制代码
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/router/routes.dart';

// 全局key,用于无context跳转的情况
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

class NavigatorUtil {
  // 无context跳转
  static void push(
    String path, {
    bool replace = false,
    bool clearStack = false,
    Object? arguments,
    TransitionType? transition,
  }) {
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: transition ?? TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context replase
  static void replase(String path,
      {bool replace = true, bool clearStack = false, Object? arguments}) {
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context,清空路由栈跳转,一般用于跳转首页这种情况
  static void switchTab(String path,
      {bool replace = false, bool clearStack = true, Object? arguments}) {
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context返回,并指定路由返回多少层,默认返回上一页面, 返回带参数params
  static void back({int count = 1, Object? params}) {
    NavigatorState state = Navigator.of(navigatorKey.currentContext!);
    while (count-- > 0) {
      state = state..pop(params);
    }
  }
}

main.dart 配置

dart 复制代码
import 'package:planx_app/router/navigator_util.dart';
import 'package:planx_app/router/routes.dart';
// ...
MaterialApp(
  // ...
  // 配置路由
  onGenerateRoute: Routes.router.generator,
  // 指定路由的全局key
  navigatorKey: navigatorKey,
);

使用

dart 复制代码
NavigatorUtil.push(Routes.routerPage);

传递参数

一、传递params参数

  • 新建路由接收参数页面

router_params_page.dart

dart 复制代码
class RouterParamsPage extends StatelessWidget {
  const RouterParamsPage({Key? key, required this.content}) : super(key: key);
  // 用来接收路由传递过来的参数
  final String content;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //....
      body: Center(
        child: Text(content), // 将参数显示到页面
      ),
    );
  }
}
  • 配置路由

lib/router/routes.dart

dart 复制代码
class Routes {
	//...
  // 路由传递参数页面
  static String routerParamPage = "/routerParam";
  static _initRouter() {
    // ...
    // 路由传递参数页面
    router.define(routerParamPage,
        handler: Handler(handlerFunc: (_, Map<String, dynamic> params) {
      // 获取路由参数
      String routerParam = params["content"]?[0];
      return RouterParamsPage(content: routerParam);
    }));
  }
	// ...
}

使用:路由跳转

  • 相当于直接在url后面拼接参数
dart 复制代码
// 传递参数
NavigatorUtil.push('${Routes.routerParamPage}?content=params11111');

参数带有特殊字符和中文时无法接收(比如: "www.baidu.com")

  • 这种情况需要考虑进行encode这样保证参数正常
  • 且通过上述的方法传递参数,每次都要拼接,并不优雅,我们顺便进行改造一下
改造NavigatorUtil方法,加密参数
  • 以下封装是完整版本

lib/router/navigator_util.dart 加密

dart 复制代码
import 'dart:convert';
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:planx_app/router/routes.dart';

// 全局key,用于无context跳转的情况
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

class NavigatorUtil {
  // 这里进行加密
  // 处理url参数拼接
  static String _getPathParams({Map<String, String>? params, path}) {
    if (params != null) {
      // Utf8Encoder,解决参数有特殊字符,中文不能传递的情况
      String p = params.entries
          .map((e) =>
              '${e.key}=${jsonEncode(const Utf8Encoder().convert(e.value))}')
          .join('&');
      path = '$path?$p';
    }
    return path;
  }

  // 无context跳转
  static void push(
    String path, {
    Map<String, String>? params,
    bool replace = false,
    bool clearStack = false,
    Object? arguments,
    TransitionType? transition,
  }) {
    // 拼接params参数
    path = _getPathParams(params: params, path: path);
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: transition ?? TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context replase
  static void replase(
    String path, {
    Map<String, String>? params,
    bool replace = true,
    bool clearStack = false,
    Object? arguments,
  }) {
    // 拼接params参数
    path = _getPathParams(params: params, path: path);
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context,清空路由栈跳转,一般用于跳转首页这种情况
  static void switchTab(
    String path, {
    Map<String, String>? params,
    bool replace = false,
    bool clearStack = true,
    Object? arguments,
  }) {
    // 拼接params参数
    path = _getPathParams(params: params, path: path);
    Routes.router.navigateTo(
      navigatorKey.currentContext!,
      path,
      replace: replace,
      clearStack: clearStack,
      transition: TransitionType.inFromRight,
      // routeSettings需要在对应页面接收:ModalRoute.of(context)?.settings.arguments;
      routeSettings: RouteSettings(
        arguments: arguments,
      ),
    );
  }

  // 无context返回,并指定路由返回多少层,默认返回上一页面, 返回带参数params
  static void back({int count = 1, Object? arguments}) {
    NavigatorState state = Navigator.of(navigatorKey.currentContext!);
    while (count-- > 0) {
      state = state..pop(arguments);
    }
  }
}
解码
  • 在路由定义位置解码

lib/router/routes.dart

dart 复制代码
  // 路由传递参数页面
    router.define(routerParamPage,
        handler: Handler(handlerFunc: (_, Map<String, dynamic> params) {
      // 获取路由参数
      String routerParam = _decodeParams(params["content"]?[0]);
      return RouterParamsPage(content: routerParam);
    }));

//...
  ///字符串解码,中文不能传递等问题
  static _decodeParams(String params) {
    List<int> list = [];
    jsonDecode(params).forEach(list.add);
    return const Utf8Decoder().convert(list);
  }

使用:

dart 复制代码
// 传递参数
NavigatorUtil.push(Routes.routerParamPage, params: {"content": "https://www.bd的收费吗,是打开就好aidu.com"});

二、传递类实例参数

  • 使用上面的NavigatorUtil方法,我们已经可以传递类参数了

使用页面:

dart 复制代码
// 传递参数,arguments可以接收一个类作为参数,Person是自己定义的类
NavigatorUtil.push(Routes.routerInstancePage,arguments: Person(name: "terry", age: 40));

接收,需要在build中接收

dart 复制代码
Widget build(BuildContext context) {
  // 接收参数
  Person p = (ModalRoute.of(context)?.settings.arguments as Person);
  return Scaffold(
    appBar: AppBar(title: Text('路由传递类参数')),
    body: Center(
      child: Column(
        children: [
          Text('ddd'),
          Text('姓名${p.name}'),
          Text('年龄${p.age}'),
        ],
      )),
  );
}
相关推荐
xiao-xiang16 分钟前
jenkins-通过api获取所有job及最新build信息
前端·servlet·jenkins
C语言魔术师33 分钟前
【小游戏篇】三子棋游戏
前端·算法·游戏
匹马夕阳2 小时前
Vue 3中导航守卫(Navigation Guard)结合Axios实现token认证机制
前端·javascript·vue.js
你熬夜了吗?2 小时前
日历热力图,月度数据可视化图表(日活跃图、格子图)vue组件
前端·vue.js·信息可视化
桂月二二8 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062069 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb9 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角9 小时前
CSS 颜色
前端·css
九酒10 小时前
从UI稿到代码优化,看Trae AI 编辑器如何帮助开发者提效
前端·trae
浪浪山小白兔10 小时前
HTML5 新表单属性详解
前端·html·html5