小型网站设计,网站备案容易吗,百度搜索引擎优化方案,深圳商业网站建设哪家好前言
欢迎来到第二篇文章#xff0c;这也是第二个难题#xff0c;就是原有的移动端本身一些页面H5的形式去呈现#xff08;webview#xff09;#xff0c;例如某些需要动态更换内容的页面#xff0c;某些活动页面、支付页面#xff0c;不仅仅做页面呈现#xff0c;还包…前言
欢迎来到第二篇文章这也是第二个难题就是原有的移动端本身一些页面H5的形式去呈现webview例如某些需要动态更换内容的页面某些活动页面、支付页面不仅仅做页面呈现还包括一些数据交互那么在项目初期我们尝试使用过了官方提供的webview但是功能比较有限因此我们选择了flutter_inappwebview这个插件
官网webview
https://pub.dev/packages/webview_flutterflutter_inappwebview
https://pub.dev/packages/flutter_inappwebview本文以flutter_inappwebview为案例将陈述我将Flutter编译成web之后如果去处理flutter_inappwebview的。
原理
我想在讲之前先讲讲什么是webview
实际上对我来说webview应该相对于原生端而已ios、android是由原生提供的底层网页环境容器去呈现网页内容那么不同端他们提供的环境当然是不一样的因为网页内核不一样那么也会造成很多的差异所以为了抹平这些差异才会提供第三方插件封装公共的api供顶层调用底层由各个平台去进行实现。
例如我之前的文章提到过的数据交互本质上就是在当前环境去注入某些方法、某些类去给网页容器提供交互的能力。
那么对于flutter_inappwebview而言它给每一个网页容器提供了一个控制器这个控制器有一个addJavaScriptHandler方法可以连接到网页容器实现监听和传输数据同时给网页容器放了一个公共的类window.flutter_inappwebview类提供网页传输数据到客户端的能力。
那么我说webview应该相对于原生端而已因为Flutter在编译成web之后本质上就是web那么之前的网页就不能叫webview应该叫iframe。
那么我们的问题实际上就是web和iframe的数据交互问题。
实现
那么如果你明白本质是web和iframe的数据交互问题你就明白为什么addJavaScriptHandler方法在web平台没有实现的原因因为压根就不需要注入他们本身就已经在一个环境下面了。
由于浏览器有同源策略所以我们还是使用postMessgae的方法但有一些地方需要注意。
实际上flutter_inappwebview有对web端的某些api进行封装编译成web那么之前的iframe的配置在flutter_inappwebview的options里面也会存在。
InAppWebViewSettings getInAppWebViewGroupOptions() {return InAppWebViewSettings()..useShouldInterceptAjaxRequest false..useShouldInterceptFetchRequest false..supportZoom true..clearCache true..iframeName my_ifram //设定ifame的名称这个就是给web环境使用的..mediaPlaybackRequiresUserGesture true..transparentBackground true..allowsInlineMediaPlayback false;}同样验证的方式你可以编译成web之后之前的webview在浏览器标签上也可以得知上iframe。
我们可以看编译之后的产物
首先id固定为flutter_inappwebview-0有csp防止内部js脚本攻击部分浏览器不可用有sandbox模式也就是沙箱模式可以进行配置对iframe做一些限制src转成hash链接默认为全屏模式
和iframe通信的方式网上有很多方法我这里不过多赘述。
父页面发送 //获取子iframe通过name属性或者直接拿第一个iframeweb.HTMLIFrameElement childIframe web.document.getElementById(flutter_inappwebview-0) as web.HTMLIFrameElement;Map data {user: {token: 1111}};JSString msg jsonEncode(data).toJS;//给子ifram传递数据// childIframe.contentWindow?.postMessage(msg, *.toJS);//这种方式是不行的childIframe.contentWindowCrossOrigin?.postMessage(msg, *.toJS);父页面接收
//监听子组件传递过来的消息web.window.addEventListener(message, callback.toJS);void callback(web.Event e) {print(收到js交互${e});}iframe发送
window.top.postMessage(hello, *)iframe接收
window.addEventListener(message, (event) {console.log(ssss, event.data)})难点
条件编译
尽管Flutter支持web端
但当编译成web端时此时如果使用到了io库(Platform相关)都会在编译时报错。
当编译成原生端使用web端相关的库web、js库同样也会在编译时报错。
那么你就需要进行文件的替换工作让Flutter在编译时根据不同的端去引入不同的文件。
比如这一段代码 web.window.addEventListener(message, callback.toJS);void callback(web.Event e) {print(收到js交互${e});}这里我们需要一定要使用到web库相关的内容才有window环境以及调用addEventListener但是你在原生端这段代码会让你在编译时就报错了。 因此你需要去做文件替换。
自己创建两个文件
import ./vm/ai_web_js.dart if (kIsWeb) dart:js_interop;
import ./vm/ai_web_window.dart if (kIsWeb) package:web/web.dart as web;在原生端使用的是我们自己写的文件实现的是空方法。
在web端使用对应的库文件
链接为hash链接加载空白的问题
当链接为hash链接时iframe会将src从链接转换成另外的格式文件data:text/html
js有提供一个内置的api为encodeURIComponent
比如有一个html为
div idmyDivh1Hello, World!/h1pThis is a sample HTML code./p
/div
通过api编码之后变成了类似这样
%3Cdiv%20class%3D%22s-skin-container%20s-isindex-wrap%20skin-gray-event%22%3E%3C%2Fdiv%3E%3Cdiv%20id%3D%22head%22%20class%3D%22%22%3E%3Cdiv%20id%3D%22s_top_wrap%22%20class%3D%22s-top-wrap%20s-isindex-wrap%20%22%20style%3D%22left%3A%200px%3B%22%3E%3Cdiv%20class%3D%22s-top-nav%22%3E%3C%2Fdiv%3E%3Cdiv%20class%3D%22s-center-box%22%3E%3C%2Fdiv%3E%3C%2Fdiv%3E%3Cdiv%20id%3D%22s-top-left%22%20class%3D%22s-top-left-new%20s-isindex-wrap%22%3E%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20.aitab-image-long%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width%3A%2049px%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20height%3A%2014px%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20margin-bottom%3A%20-2px%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20.aitab-image-short%20%7B%0A%20%20%20%20%20%20%20%20%20%然后再加上前缀data:text/html,这种特殊格式标识变成URL
const dataURL data:text/html, encodedHTML;放入iframe的src中去进行处理。
但是当我们的链接是hash链接我们打包成web项目可以选择hash路由或者history路由hash路由是通过监听hash值的变化去响应不同的js数据在同一个html去做不同的渲染。
那么这个时候就要求你的html中的js必须能够正常请求响应才能触发监听去做数据的呈现。
测试发现当链接为hash链接时能正常展示html但是内部需要的js已经不做网络请求了因为根本就不是加载链接而是加载一个普通的文本
!DOCTYPE html
html langzh-CNheadmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgetitleaiyjcp/titlescriptvar coverSupport CSSin window typeof CSS.supports function (CSS.supports(top: env(a)) || CSS.supports(top: constant(a)))document.write(meta nameviewport contentwidthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scale1.0 (coverSupport ? , viewport-fitcover : ) /)/scriptlink relstylesheet href./static/index.2da1efab.css/headbodynoscriptstrongPlease enable JavaScript to continue./strong/noscriptdiv idapp/divscript src./static/js/chunk-vendors.bc6b93b6.js/scriptscript src./static/js/index.d07f5f7d.js/script/body
/html
那么至此我们就发现了问题了
原因在于flutter_inappwebview会对url获取html文本进行转码变成特殊的url格式datatext/html格式但是加载出html之后内部需要的js和css都不进行网络请求获取导致无法监听到hash值的变化以及所需要的资源导致可能出现页面空白如果你使用hash路由或者样式丢失如果你使用history路由
那么就有三种解决方案
第一种不要让插件对URL进行转码第二种研究如何让转码还原之后的html再次进行网络请求加载出需要的JS和CSS文件第三种再嵌套一层iframe插件对第一层进行转码还原之后内部还是一个iframe这个时候内部的iframe就不会对src进行再次转码了但是这种情况数据通信又需要做改变由父子关系变成父到子再到孙子关系
问题出在配置上面 之前在原生端对url做了处理 key: webViewKey,initialUrlRequest: URLRequest(url: url.startsWith(http)? WebUri.uri(Uri.parse(url)): WebUri.uri(Uri.file(url)),但是在web环境这种方式会对url进行转码因此你需要这么写在web环境
URLRequest(url: WebUri(url)尽管这种方式解决了编译和运行的问题但是却失去了相应的代码提示如果你有更好的方法欢迎在下方提出下一篇会解决Dio以及请求相关的问题 文章转载自: http://www.morning.tpdg.cn.gov.cn.tpdg.cn http://www.morning.pcjw.cn.gov.cn.pcjw.cn http://www.morning.tyhfz.cn.gov.cn.tyhfz.cn http://www.morning.cmdfh.cn.gov.cn.cmdfh.cn http://www.morning.bkcnq.cn.gov.cn.bkcnq.cn http://www.morning.bbgn.cn.gov.cn.bbgn.cn http://www.morning.mqldj.cn.gov.cn.mqldj.cn http://www.morning.vjdofuj.cn.gov.cn.vjdofuj.cn http://www.morning.mlfgx.cn.gov.cn.mlfgx.cn http://www.morning.rsszk.cn.gov.cn.rsszk.cn http://www.morning.tqjks.cn.gov.cn.tqjks.cn http://www.morning.qrlsy.cn.gov.cn.qrlsy.cn http://www.morning.bdgb.cn.gov.cn.bdgb.cn http://www.morning.hlfnh.cn.gov.cn.hlfnh.cn http://www.morning.kztpn.cn.gov.cn.kztpn.cn http://www.morning.frnjm.cn.gov.cn.frnjm.cn http://www.morning.bswhr.cn.gov.cn.bswhr.cn http://www.morning.nyqb.cn.gov.cn.nyqb.cn http://www.morning.pcqxr.cn.gov.cn.pcqxr.cn http://www.morning.ubpsa.cn.gov.cn.ubpsa.cn http://www.morning.pwsnr.cn.gov.cn.pwsnr.cn http://www.morning.rlqwz.cn.gov.cn.rlqwz.cn http://www.morning.bhdtx.cn.gov.cn.bhdtx.cn http://www.morning.ykgp.cn.gov.cn.ykgp.cn http://www.morning.tcpnp.cn.gov.cn.tcpnp.cn http://www.morning.sqtsl.cn.gov.cn.sqtsl.cn http://www.morning.phwmj.cn.gov.cn.phwmj.cn http://www.morning.kzpy.cn.gov.cn.kzpy.cn http://www.morning.syrzl.cn.gov.cn.syrzl.cn http://www.morning.qnjcx.cn.gov.cn.qnjcx.cn http://www.morning.hmnhp.cn.gov.cn.hmnhp.cn http://www.morning.wdnkp.cn.gov.cn.wdnkp.cn http://www.morning.trnl.cn.gov.cn.trnl.cn http://www.morning.liyixun.com.gov.cn.liyixun.com http://www.morning.tqdlk.cn.gov.cn.tqdlk.cn http://www.morning.qsctt.cn.gov.cn.qsctt.cn http://www.morning.xckqs.cn.gov.cn.xckqs.cn http://www.morning.ggmls.cn.gov.cn.ggmls.cn http://www.morning.ylpwc.cn.gov.cn.ylpwc.cn http://www.morning.rrxgx.cn.gov.cn.rrxgx.cn http://www.morning.jxdhc.cn.gov.cn.jxdhc.cn http://www.morning.lxcwh.cn.gov.cn.lxcwh.cn http://www.morning.frzdt.cn.gov.cn.frzdt.cn http://www.morning.ddfp.cn.gov.cn.ddfp.cn http://www.morning.zbgqt.cn.gov.cn.zbgqt.cn http://www.morning.fprll.cn.gov.cn.fprll.cn http://www.morning.huihuangwh.cn.gov.cn.huihuangwh.cn http://www.morning.nrll.cn.gov.cn.nrll.cn http://www.morning.tsyny.cn.gov.cn.tsyny.cn http://www.morning.lwmzp.cn.gov.cn.lwmzp.cn http://www.morning.gnjkn.cn.gov.cn.gnjkn.cn http://www.morning.mfjfh.cn.gov.cn.mfjfh.cn http://www.morning.xhrws.cn.gov.cn.xhrws.cn http://www.morning.mdpkf.cn.gov.cn.mdpkf.cn http://www.morning.gnyhc.cn.gov.cn.gnyhc.cn http://www.morning.gsyns.cn.gov.cn.gsyns.cn http://www.morning.wdshp.cn.gov.cn.wdshp.cn http://www.morning.ntzfj.cn.gov.cn.ntzfj.cn http://www.morning.wlfxn.cn.gov.cn.wlfxn.cn http://www.morning.xywfz.cn.gov.cn.xywfz.cn http://www.morning.mgtrc.cn.gov.cn.mgtrc.cn http://www.morning.bsrcr.cn.gov.cn.bsrcr.cn http://www.morning.lgtzd.cn.gov.cn.lgtzd.cn http://www.morning.ckctj.cn.gov.cn.ckctj.cn http://www.morning.slmbg.cn.gov.cn.slmbg.cn http://www.morning.ylph.cn.gov.cn.ylph.cn http://www.morning.rkdw.cn.gov.cn.rkdw.cn http://www.morning.rwpjq.cn.gov.cn.rwpjq.cn http://www.morning.rmpfh.cn.gov.cn.rmpfh.cn http://www.morning.jykzy.cn.gov.cn.jykzy.cn http://www.morning.fkrzx.cn.gov.cn.fkrzx.cn http://www.morning.bmssj.cn.gov.cn.bmssj.cn http://www.morning.tsdqr.cn.gov.cn.tsdqr.cn http://www.morning.lgrkr.cn.gov.cn.lgrkr.cn http://www.morning.ljwyc.cn.gov.cn.ljwyc.cn http://www.morning.qflcb.cn.gov.cn.qflcb.cn http://www.morning.rkwlg.cn.gov.cn.rkwlg.cn http://www.morning.qlkjh.cn.gov.cn.qlkjh.cn http://www.morning.hpjpy.cn.gov.cn.hpjpy.cn http://www.morning.zxxys.cn.gov.cn.zxxys.cn