波动网络中的命名路线如何具有URL参数?

时间:2019-08-19 08:20:46

标签: web flutter dart

我正在构建一个Web应用程序,该应用程序需要具有一个获取帖子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
    );
  }
}

7 个答案:

答案 0 :(得分:2)

我是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

答案 1 :(得分:2)

tl; dr

//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"

下钻

在理想环境中,您可以使用queryParameters访问Uri.base.queryParameters,因为:

Uri.base

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

但是目前存在一个问题,您的路径中有#/会弄乱Uri.base对Uri的解释。
遵循issue #33245,直到解决此问题为止,您将可以使用Uri.base.queryParameters

答案 2 :(得分:1)

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

之所以这样做,是因为这似乎是Flutter允许我打开其中包含ID的URL(不返回404)的唯一方法。

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

我的目标:我有一个一页的Web应用程序,该应用程序一次只显示一个发票,该发票对应于URL中的ID。

我的网址

app.com /#/ xLZppqzSiSxaFu4PB7Ui

URL末尾的数字是FireStore文档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”发送到“发票”小部件。

答案 3 :(得分:1)

这是另一种方法:

我的网址格式: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();
              },
            );
          ;
        },

答案 4 :(得分:0)

请点击此链接,以获取更多信息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

像网络一样吸引人

答案 5 :(得分:0)

这就是我的方法。您可以根据需要进行编辑。如果要使用?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());
  }
}

答案 6 :(得分:0)

flutter_modular 添加到您的 Flutter Web 项目。

当前版本:flutter_modular: ^3.1.1

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

URL /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()));