小编给大家分享一下Flutter WebView与JS如何互相调用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
WebView与JS互相调用是一个刚需,但是貌似现在大家写的文章讲的都不是很清楚,我这个简易指南简单粗暴地分为两部分:JS调用Flutter和Flutter调用JS,拒绝花里胡哨,保证一看就懂,一学就会。
开始之前先简单了解一下官方WebView所包含的API:
onWebViewCreated:在WebView创建完成后调用,只会被调用一次;
initialUrl:初始load的url;
javascriptMode:JS执行模式(是否允许JS执行);
javascriptChannels:JS和Flutter通信的Channel;
navigationDelegate:路由委托(可以通过在此处拦截url实现JS调用Flutter部分);
gestureRecognizers:手势监听;
onPageFinished:WebView加载完毕时的回调。
JS调用Flutter
JS调用Flutter有两种方法:使用javascriptChannels发送消息和使用路由委托(navigationDelegate)拦截url。
方法1:使用javascriptChannels发送消息
javascriptChannels参数可以传入一组Channels,我们可以定义一个_alertJavascriptChannel变量,这个channel用来控制JS调用Flutter的toast功能:
JavascriptChannel _alertJavascriptChannel(BuildContext context) { return JavascriptChannel( name: 'Toast', onMessageReceived: (JavascriptMessage message) { showToast(message.message); }); } WebView( avascriptChannels: <JavascriptChannel>[ _alertJavascriptChannel(context), ].toSet(), ;
在上面的代码中,我们定义了一个_alertJavascriptChannel变量,并给它起了个name叫Toast,这个name属性接收的是一个字符串,它代表了JS调用Flutter时,双方共同商定好了的一个协议,JS通过这个name去post对应的信息给Flutter(API为name.postMessage('xxxxxx'))。我们在网页部分写一个简单的button,点击后开始JS调用Flutter的逻辑:
<button onclick="callFlutter()">callFlutter</button> function callFlutter(){ Toast.postMessage("JS调用了Flutter"); }
onMessageReceived为Flutter接收到了JS的消息之后的回调,我们可以通过message.message来获取JS发给我们的消息内容。JavascriptMessage类暂时只有一个String类型的message成员变量,所以如果需要传递复杂数据,可以通过传递json字符串来解决。
代码重点:JavascriptChannel中的name要与JS中的name.postMessage()相对应!!
方法2:使用路由委托navigationDelegate拦截url
navigationDelegate回调在每次网页路由地址发生变化的时候都会触发,因此我们可以拦截特定的url来实现JS调用Flutter。
同样的,我们在网页部分写一个简单的button,点击后跳转路由"js://webview?arg1=111&args2=222"。我们可以和客户端协商好一个scheme,比如这个例子里面就是js://webview,我们可以在query string上带上我们想要传递的参数:
<button onclick="callFlutter()">callFlutter</button> function callFlutter(){ /*约定的url协议为:js://webview?arg1=111&arg2=222*/ document.location = "js://webview?arg1=111&args2=222"; }
在Flutter端,我们就可以在navigationDelegate回调中拦截这个符合js://webviewscheme的路由地址了:
navigationDelegate: (NavigationRequest request) { if (request.url.startsWith('js://webview')) { showToast('JS调用了Flutter By navigationDelegate'); print('blocking navigation to $request}'); return NavigationDecision.prevent; } print('allowing navigation to $request'); return NavigationDecision.navigate; },
我们通过return不同的值,告诉WebView怎么处理这个路由:
NavigationDecision.prevent:阻止路由替换;
NavigationDecision.navigate:允许路由替换。
Flutter调用JS
在WebView创建完成之后,我们可以拿到一个WebViewController,通过它的evaluateJavascript()方法,我们可以执行JS语句:
onWebViewCreated: (WebViewController webViewController) { _controller = webViewController; }, ······ floatingActionButton: FloatingActionButton( onPressed: () { _controller ?.evaluateJavascript('callJS("visible")') ?.then((result) { // You can handle JS result here. }); }, child: Text('call JS'), ),
<p id="p1" > Flutter 调用了 JS. Flutter 调用了 JS. Flutter 调用了 JS. </p> function callJS(message){ document.getElementById("p1").style.visibility = message; }
在上面的例子中,我们点击floatingActionButton后,就会去执行JS中的callJS()方法了,具体UI体现为:将隐藏的段落重新显示。evaluateJavascript()返回值是一个Future,因此我们可以接收JS给我们的返回值,返回值格式请阅读官方API注释。
这里要注意的是,evaluateJavascript()方法,Flutter建议我们在onPageFinished回调之后去执行,以保证所有的HTML都已经加载完毕了。因此在实际开发中,我这里展示的这种直接将onWebViewCreated中的controller赋值的方法是不可取的,应该是使用FutureBuilder之类的方式去实现比较优雅
看完了这篇文章,相信你对“Flutter WebView与JS如何互相调用”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。