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}'),
        ],
      )),
  );
}
相关推荐
学习使我快乐012 小时前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
bobostudio19952 小时前
TypeScript 设计模式之【策略模式】
前端·javascript·设计模式·typescript·策略模式
黄尚圈圈3 小时前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
浮华似水4 小时前
简洁之道 - React Hook Form
前端
正小安6 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
_.Switch7 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光7 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   7 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   7 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web8 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery