Flutter开发中,项目中我使用Get
库进行路由管理
和状态管理
。其页面跳转使用Get.toNamed()
的方式是比较方便的,参数传递方式也比较简单,例如
Get.toNamed( AppRouters.myOrderList, arguments: { "fromExternal": true, "orderStatus": 2 } );
可以在对应页面的Controller中onInit
方法中,获取到传递过来的参数。
在web的场景中,情况会变得稍微有点复杂。 在web中除了页面跳转以及参数传递外,它的每个页面都有个对应的url
,用户可以通过浏览器直接访问到某一个指定的页面,跟App相比,这点就脱离了程序的本身的掌控范围。直接通过Url来进入到指定页面,就需要可以通过URL传递参数的需求。
Flutter Web中的路由模式
Flutter Web
应用支持两种基于URL的路由配置方式:Hash(默认) 和 Path。
1. Hash(默认)
路径使用 # + 锚点标识符 读写,例如 flutterexample.dev/#/path/to/screen
。
2. Path
路径使用非 # 读写,例如 flutterexample.dev/path/to/screen
。
不管使用的是Hash模式还是Path模式,其参数传递的方式都是相同的。如果也是使用Get来做路由管理的话,在依赖注入的设置中,GetPage设置如下
GetPage( name: "/deviceDetail/:deviceId", page: () => const DeviceDetailPage(), binding: DeviceDetailBinding(), ),
其中name设置的/deviceDetail/:deviceId
中:deviceId
就代表设备id的参数。在浏览器中url中通过链接 http://localhost:8080/deviceDetail/123456
这样的方式就可以进入到指定页面,并可以在对应的页面中的controller中获取到这个参数。
注意:与上述
Get.toNamed()
中arguments
传递参数不同,通过Url路径传递参数的话,需要使用Get.parameters
才能获取到对应的参数。 而Get.toNamed()
方法中,通过arguments
参数传递的参数,则需要通过Get.arguments
来获取参数。
# Hash模式转为Path模式
在web中,浏览器中的Url使用Hash模式,也就是带有 # 的url的方式其实并不常见。有时候会感觉这种方式比较奇怪,那么是否可以去掉这个 # 呢?当然可以的。
方式很简单,使用一个插件 url_strategy ,稍加配置就可以实现这个功能。
url_strategy 的使用
安装好插件后,配置方式如下,只需要设置 setPathUrlStrategy();
。
import 'package:url_strategy/url_strategy.dart'; void main() { // Here we set the URL strategy for our web app. // It is safe to call this function when running on mobile or desktop as well. setPathUrlStrategy(); runApp(MyApp()); }
除了这个之外,还需要在项目的web目录下,在web/index.html
的<head>
标签中,添加
<base href="/">
如果在web/index.html
的<head>
标签中有设置<base href="$FLUTTER_BASE_HREF">
,将其去掉。换为<base href="/">
。
这时候,就完成了Url中去掉#的工作。
去掉 # 后,上线后问题,Nginx配置的修改
上述修改完成后,用Android stdio等工具进行调试时,发现没有什么问题。但是当项目打包放在服务器下面进行访问的时候,你会发现出现一个奇怪的问题。正常从首页开始,一步步点击测试的时候没有任何问题,但是,当直接通过url访问一个非首页的页面时,会出现404 not found的错误。
这是因为Nginx的配置不支持单页应用(SPA)的路由导致的。为了解决这个问题,则需要对Nginx的配置进行修改。
在服务器块内,添加以下配置
location / { try_files $uri $uri/ /index.html; }
这个配置告诉Nginx,当请求的Url不存在时,返回index.html
文件。这将允许Flutter Web应用处理所有的路由请求。
然后重启Nginx服务使配置生效。至此,线上的Flutter Web也可以正常访问对应的页面。