起因
机缘巧合之下,我得到了一个flutter web实践机会,这里记录一下flutter web用于h5的实践。
遇到的问题&解决方案
1、路由&传值
这个问题困扰的时间比较长。在APP的开发里是可以不使用路由的,而web的页面里路由是必要的。
使用flutter build web 命令,生成的代码里,默认的路由是带#号的,其实这并没有问题。但是引发了一个问题:路径后边的传值,得不到了!
代码是这样的:
dart
String href = html.window.location.href;
Uri uri = Uri.parse(href);
String code = uri.queryParameters['code'] ?? "";
由于#的存在,href是无论如何得不到#后边的值。
后来查询,使用url_strategy插件即可解决这个问题。这个方法试了,在测试环境是没问题的,一旦把代码部署在正式环境,那么页面就白屏了。。。用flutter web开发h5,问题就像打地鼠,打下去一个又上来一个...
办法总比问题多,路径后边的值是一定要获取到的,怎么办?
换一个思路解决:得到当前的全部地址,手动把#去掉,然后再使用queryParameters。(是否还有更好的解决办法?)
dart
//获得全部地址的代码
html.window.location.toString();
2、双重js交互
这个问题困扰的时间是最长的。普通的js交互无非就是h5调用原生的方法,或者原生调用h5的方法。
然而这里就不同了。由于这里的h5是flutter web实现的,那么在APP里使用了这个h5页面,点击h5的按钮,调取APP的方法,如何实现?(同为flutter,但是所在的场地不同)
网上好像没有现成的解决方案,但之前的经验以及与同事的讨论带给了我灵感:flutter web里首先调用js方法,然后js方法里调用APP的方法。这样似乎是行的通的,于是我开始了尝试。
举个例子:点击h5里的按钮,实现APP的返回功能,关键代码展示:
flutter web 源码:
arduino
//在flutter web项目里,点击按钮调用这个方法,引号里的名称即为js代码里方法的名称
js.context.callMethod('h5back');
flutter web生成的html文件修改,源码:
dart
<script>
......
//appBack,这个名称是APP里定义的方法名称。
function h5back(){
appBack.postMessage(''); //注意,方法里的引号是必传的,否则方法调不通。
}
</script>
APP里定义的方法,源码:
dart
//这里是flutter app里使用 webview_flutter插件,对应WebviewWidget里的curController里的代码。
..addJavaScriptChannel("appBack", onMessageReceived: (JavaScriptMessage msg) {
//返回事件
print("这里是APP的返回事件");
})
扩展:如果h5里我想传参,该当如何?(已解决,留给读者思考)
3、奇怪的问题:iOS设备js交互
这个问题困扰的时间是第二长的。主要是这个问题很奇怪,同样的情况安卓手机没有出现,但是iOS手机出现了。
具体情况是这样的:点击h5里的按钮,调起APP的方法,APP里这个方法是弹一个底部弹窗。iOS机型奇怪的地方在于,这个底部弹窗只有第一次点击有效,第二次点击则没有响应!!!定位花了一部分时间。经过调试,发现如果不弹窗,h5的方法能正常使用。是底部弹窗影响了iOS机型里后续的js交互事件。
目前已经解决了,但是这个问题本质上还需要一个答案...
待解决的问题
1、加载缓慢问题
打开页面,由于需要加载flutter的字体文件,大概1M多,导致页面缓慢,尤其是刚打开的时候字体是叉号!这个情况后续有待优化。
2、路由问题
目前的路由是带#号的,后续考虑优化成不带#号。
总结
实践证明:使用flutter web作为h5,在理论和实践上都是可行的。
在flutter APP里使用flutter web的h5页面,遇到的问题不止这些,但这几个是比较主要的情况。希望这次趟的坑,能给后边走这趟路的人有所帮助。
悄悄感谢同事和leader的帮助~本期活动的地址在这里,欢迎大家体验,并提出宝贵的意见!
bash
活动地址(手动复制后打开):
https://m.evimed.com/flutter/#/register?inviteCode=ILCmYXUj8n