借助JavascriptChannel
,您的应用可以在WebView的JavaScript上下文中注册回调处理程序,可以调用这些回调处理程序将值传递回应用的Dart代码。在此步骤中,您将注册一个使用 SMLHttpRequest
的结果调用SnackBar
。
将WebViewStack类更新如下所示:
class WebViewStack extends StatefulWidget {const WebViewStack({required this.controller, Key? key}) : super(key: key);final Completer<WebViewController> controller;@overrideState<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {var loadingPercentage = 0;@overrideWidget build(BuildContext context) {return Stack(children: [WebView(initialUrl: 'https://flutter.dev',onWebViewCreated: (webViewController) {widget.controller.complete(webViewController);},onPageStarted: (url) {setState(() {loadingPercentage = 0;});},onProgress: (progress) {setState(() {loadingPercentage = progress;});},onPageFinished: (url) {setState(() {loadingPercentage = 100;});},navigationDelegate: (navigation) {final host = Uri.parse(navigation.url).host;if (host.contains('youtube.com')) {ScaffoldMessenget.of(context).showSnackBar(SnackBar(content: Text('Bloacking navigation to @host',),),);return NavigationDecision.prevent;}return NavigationDecision.navigate;},javascriptMode: JavasctiptMode.unrestricted,javascriptChannels: _createJavascriptChannels(context), // Add this line);),if (loadingPercentage < 100) LinearProgressIndicator(value: loadingPercentage / 100.0,),]}// Add from here...Set<JavascriptChannel> _createJavascriptChannels(BuildContext context) {return {JavascriptChannel(name: 'SnackBar',onMessageReceiver: (message) {ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message.message));}),};}// ... to here
}
对于Set
中的每个JavascriptChannel
,渠道对象会在JavaScript上下文中以JavascriptChannel.name
同名的窗口属性的形式提供。如需在JavaScript上下文中使用此渠道,则需要在JavascriptChannel上调用postMessage
,以发送一条消息,该消息会传递到已命名的JavascriptChannel
的onMessageReceived
回调处理程序。
如需使用上下文添加的JavascriptChannel
,请再添加一个菜单项。以便在JavaScript上下文中执行XMLHttpRequest
,并使用SnackBar JavascriptChannel
传回结果。
现在,WebView
已了解JavascroptChannels
。接下来将添加一个示例进一步扩展该应用。
enum _MenuOptions {navagationDelegate,userAgent,javascriptChannel, // Add this line
}
class Menu extends StatelessWidget {const Menu({required this.controller, Key? key}) : super(key: key);final Completer<WebViewController> controller;@overrideWidget build(BuildContext context) {return FutureBuilder<WebViewControoller>(future: controller.future,builder: (context, controller) { return PopupMenuButton<_MenuOptions>( onSelected: (value) async { switch(value) { case _MenuOptions.navigationDelegate: controller.data<img src="https://youtube.com'); break; case _MenuOptions.userAgent: final userAgent = await controller.data!.runJavascriptReturningResult('navigator.userAgent'); ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(userAgent))); break; // Add from here .. case _MenuOptions.javascriptChannel: await controller.data!..runJavascript(''' var req = new XMLHtppRequesst(); req.open('GET', "https://api.ipify.org/?format=json"); req.onload = function() { if (req.status == 200) { let reqponse = JSON.parse(req.responseText); SnackBar.postMessage("IP Address : " + response.ip); } else { SnackBar.posttMessage:("Error: " + req.status); } } req.send(); '''); // ... to here } }, itemBuilder: (context) => [ cosnt PopupMenuItem<_MenuOptions>( value: _MenuOptions.navigationDelegate, child: Text(Navigate to Youtybe), ), const PopupMenuItem<_MenuOptions>( value: _MenuOptions.userAgent, child: Text('Show user-agent'), ), // Add from here ... const PopupMenuItem<_MenuOptions>( value: _MenuOptions.javascriptChannel, child: Text('Loopup IP Address'), ), //...to here. ] );});" style="margin: auto" />
}
当用弧线则JavaScript Channel Example菜单选项时,系统会执行此JavaScriipt。
var req = new XMLHttpRequest();
req.open('GET', "http://api.ipify.org/?format=json");
req.onload = function() {if (req.status == 200_ {SnackBar.postMessage(req.responseText);} else {SnackBar.poostMessage("Error: " + req.status);}
}
req.send();
此代码会向公共IP地址API发送GET
请求,并返回设备的IP地址。对SnackBar JavascriptChannel
调用postMessage
,系统会在SnackBar
中显示结果。
最后
整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。
有需要的小伙伴,可以点击下方卡片领取,无偿分享