【问题标题】:命名路由如何在flutter web中具有URL参数?
【发布时间】:2019-12-24 10:42:01
【问题描述】:

我正在构建一个网络应用程序,它需要有一个获取帖子 ID 的路由,然后它将使用该 ID 获取帖子。

我怎样才能有 URL 参数让我们说/post/:id 所以 id 是参数

我的应用目前看起来像这样:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title: "Paste",
      initialRoute: "/",
      theme: ThemeData(
          primarySwatch: Colors.green,
          primaryColor: Colors.blue
      ),
      routes: {
        "/": (context) => HomePage(),
        "/post": (context) => PastieRoute()
      },
      debugShowCheckedModeBanner: false
    );
  }
}

编辑: 这是我根据@BloodLoss 尝试过的,出于某种原因,我在访问localhost:8080/post?id=123时没有得到任何东西到控制台@

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: "/",
      routes: {
        "/": (context) => HomePage(),
        "/post": (context) => PastieRoute()
      },
      onGenerateRoute: (settings) {
        if (settings.name == "/post") {
          print(settings.arguments); // Doesn't fire :(

          return MaterialPageRoute(
            builder: (context) {
              // TODO
            }
          );
        }
      },
      debugShowCheckedModeBanner: false
    );
  }
}

【问题讨论】:

标签: flutter dart flutter-web


【解决方案1】:

tl;博士

//in your example: settings.name = "/post?id=123"
final settingsUri = Uri.parse(settings.name);
//settingsUri.queryParameters is a map of all the query keys and values
final postID = settingsUri.queryParameters['id'];
print(postID); //will print "123"

向下钻取

在一个完美的世界中,您可以使用Uri.base.queryParameters 访问queryParameters,因为:

Uri.base

返回当前平台的自然基础 URI。 在浏览器中运行时,这是当前页面的当前 URL(来自 window.location.href)。 当不在浏览器中运行时,这是引用当前工作目录的文件 URI。

但目前在颤振中存在一个问题,您的路径中有 #/,这会混淆 Uri 的 Uri.base 解释。
关注issue #33245,直到这个问题得到解决,您就可以使用Uri.base.queryParameters

【讨论】:

  • "Get.rootDelegate.parameters" gor nav2 or navigation 2.0 with Getx
【解决方案2】:

请点击此链接了解更多信息https://flutter.dev/docs/cookbook/navigation/navigate-with-arguments

在你的MaterialApp

  onGenerateRoute: (settings) {
    // If you push the PassArguments route
    if (settings.name == PassArgumentsScreen.routeName) {
      // Cast the arguments to the correct type: ScreenArguments.
      final ScreenArguments args = settings.arguments;

      // Then, extract the required data from the arguments and
      // pass the data to the correct screen.
      return MaterialPageRoute(
        builder: (context) {
          return PassArgumentsScreen(
            title: args.title,
            message: args.message,
          );
        },

或者你可以使用这个插件fluro像网络一样进行本地化

【讨论】:

  • 这看起来更像是查询参数类型的东西,这不是我对 /post/:id 之类的期望,因为 id 只是一个值而不是 key-value
  • 根据我的flutter知识,你不能这样
  • 哦,好吧,我希望它会成为flutter_web的东西。
  • 你能检查我的问题编辑吗?和关于 Fluro。我认为 Flutter web 不支持它?因为没有提到它
  • @TheOnlyArtz Fluro 支持 Flutter web 吗?如果没有其他可用选项?
【解决方案3】:

我就是这样做的。您可以根据您的要求对其进行编辑。如果您想使用 ?q= 则相应地使用 split by 或 regex

这里是同时传入参数以及作为 /topic/:id 传入 url 的示例

  Route<dynamic> generateRoute(RouteSettings settings) {
  List<String> pathComponents = settings.name.split('/');
  final Map<String, dynamic> arguments = settings.arguments;
  switch ("/"+pathComponents[1]) {
    case shareTopicView:
      return MaterialPageRoute(
          builder: (context) => TopicPageLayout(topicID: pathComponents[2]));
    case internalTopicView:
      return MaterialPageRoute(
          builder: (context) => TopicPageLayout(topicID: arguments['topicID']));
    default:
      return MaterialPageRoute(builder: (context) => LandingPage());
  }
}

【讨论】:

    【解决方案4】:

    flutter_modular 添加到您的 Flutter Web 项目中。

    当前版本:flutter_modular: ^3.1.1

    读取动态路由部分:https://pub.dev/packages/flutter_modular#dynamic-routes

    网址/post?id=123的示例

    1. 使用 MaterialApp 创建您的主小部件并调用 ´´´MaterialApp().modular()´´´ 方法。

       //  app_widget.dart
       import 'package:flutter/material.dart';
       import 'package:flutter_modular/flutter_modular.dart';
      
       class AppWidget extends StatelessWidget {
         @override
         Widget build(BuildContext context) {
           return MaterialApp(
             initialRoute: "/",
           ).modular();
         }
       }
      
    2. 创建您的项目模块文件扩展模块:

       // app_module.dart
       class AppModule extends Module {
         @override
         final List<Bind> binds = [];
      
         @override
         final List<ModularRoute> routes = [
             ChildRoute('/', child: (_, __) => HomePage()),
             ChildRoute('/post', child: (_, args) => PostPage(id: args.queryParams['id'])),
        ];
       }
      

    3.在main.dart文件中,将主模块包裹在ModularApp中,用Modular对其进行初始化:

    // main.dart
    import 'package:flutter/material.dart';
    import 'package:flutter_modular/flutter_modular.dart';
    
    import 'app/app_module.dart';
    
    void main() => runApp(ModularApp(module: AppModule(), child: AppWidget()));
    

    【讨论】:

      【解决方案5】:

      这是一个使用“默认”路由作为我的主要路由的解决方法。

      我这样做是因为它似乎是 Flutter 允许我打开一个带有 ID 的 URL 的唯一方法,它不会返回 404。

      例如Flutter 似乎不尊重“?”分隔器。因此,带有 ID 的 URL 会被 Flutter 读取为未知 URL。例如。 site.com/invoice?id=999 将返回 404,即使 /invoice 设置为路由。

      我的目标:我有一个单页网络应用程序,它一次只显示一张发票,对应于 URL 中的 ID。

      我的网址

      app.com/#/xLZppqzSiSxaFu4PB7Ui

      URL 末尾的数字是 FireStore Doc ID。

      这是 MyApp 中的代码:

      onGenerateRoute: (settings) {
                List<String> pathComponents = settings.name.split('/');
                switch (settings.name) {
                  case '/':
                    return MaterialPageRoute(
                      builder: (context) => Invoice(),
                    );
                    break;
                  default:
                    return MaterialPageRoute(
                      builder: (context) => Invoice(
                        arguments: pathComponents.last,
                      ),
                    );
                }
              },
      

      这会将“xLZppqzSiSxaFu4PB7Ui”发送到“发票”小部件。

      【讨论】:

        【解决方案6】:

        这是另一种方法:

        我的网址格式:www.app.com/#/xLZppqzSiSxaFu4PB7Ui

        onGenerateRoute: (settings) {
                  List<String> pathComponents = settings.name.split('/');
                  if (pathComponents[1] == 'invoice') {
                    return MaterialPageRoute(
                      builder: (context) {
                        return Invoice(arguments: pathComponents.last);
                      },
                    );
                  } else
                    return MaterialPageRoute(
                      builder: (context) {
                        return LandingPage();
                      },
                    );
                  ;
                },
        

        【讨论】:

          【解决方案7】:

          我是 Flutter 的新手,我发现了一个古怪的解决方法,...

          import 'dart:html';
          
          String itemID;
          
          //My url looks like this,... http://localhost:57887/#item_screen/12345
          //Counted 13 characters for '#item_screen/' then got the substring as below 
          
           itemID = window.location.hash.substring(13);
           print(itemID) //12345
          

          不是很复杂,但很有效:-D

          【讨论】:

            【解决方案8】:

            使用以下示例尝试 onGenerateRoute

              final info = settings.arguments as Mediainfo?;
            
                settings = settings.copyWith(
                    name: settings.name! + "?info=" + info!.name, arguments: info);
                return MaterialPageRoute(
                    builder: (_) => MediaDetails(info: info), settings: settings);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-02-15
              • 1970-01-01
              • 2013-05-28
              • 1970-01-01
              • 1970-01-01
              • 2021-09-23
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多