如何在Flutter Web平台中获取WebView的当前URL?
解决Flutter Web中获取WebView当前页面URL的问题
方案一:升级webview_flutter_web到最新稳定版
早期的webview_flutter_web: ^0.2.3+4确实缺少直接获取当前URL的API,升级到与webview_flutter主包同步的最新版本(比如webview_flutter: ^4.4.0及对应兼容的webview_flutter_web版本)后,可通过官方API实现需求:
- 更新
pubspec.yaml依赖:
dependencies: webview_flutter: ^4.4.0 webview_flutter_web: ^0.2.3+10 # 版本号可随主包自动匹配
- 实现代码示例:
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class WebViewUrlTracker extends StatefulWidget { const WebViewUrlTracker({super.key}); @override State<WebViewUrlTracker> createState() => _WebViewUrlTrackerState(); } class _WebViewUrlTrackerState extends State<WebViewUrlTracker> { late final WebViewController _controller; String _currentUrl = ''; @override void initState() { super.initState(); _controller = WebViewController() ..loadRequest(Uri.parse('https://example.com')) ..setNavigationDelegate( NavigationDelegate( // 页面开始加载时更新URL onPageStarted: (String url) => _updateUrl(url), // 页面加载完成时更新URL onPageFinished: (String url) => _updateUrl(url), // 拦截页面跳转请求,同步更新URL onNavigationRequest: (NavigationRequest request) { _updateUrl(request.url); return NavigationDecision.navigate; }, ), ); } // 主动获取当前URL的方法 Future<void> _fetchCurrentUrl() async { final url = await _controller.currentUrl(); if (url != null) _updateUrl(url); } void _updateUrl(String url) { if (mounted) { setState(() => _currentUrl = url); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('当前URL: $_currentUrl')), body: WebViewWidget(controller: _controller), floatingActionButton: FloatingActionButton( onPressed: _fetchCurrentUrl, child: const Icon(Icons.refresh), ), ); } }
方案二:通过JavaScript交互手动监听(兼容旧版或第三方WebView包)
如果升级包仍无法满足需求,可直接利用Flutter Web与JS的通信能力,注入代码监听URL变化并同步到Flutter:
核心逻辑:
- 向WebView注入JS,监听页面加载、前进后退、哈希变化等事件
- URL变化时通过
postMessage或JavaScriptChannel通知Flutter - 在Flutter中接收消息并更新当前URL
实现代码示例:
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'dart:html' as html; class JsBasedUrlTracker extends StatefulWidget { const JsBasedUrlTracker({super.key}); @override State<JsBasedUrlTracker> createState() => _JsBasedUrlTrackerState(); } class _JsBasedUrlTrackerState extends State<JsBasedUrlTracker> { late final WebViewController _controller; String _currentUrl = ''; @override void initState() { super.initState(); // 监听JS发送的消息 html.window.addEventListener('message', (event) { final msg = (event as html.MessageEvent).data; if (msg is String && msg.startsWith('URL_UPDATE:')) { _updateUrl(msg.replaceFirst('URL_UPDATE:', '')); } }); _controller = WebViewController() ..loadRequest(Uri.parse('https://example.com')) ..setJavaScriptMode(JavaScriptMode.unrestricted) ..runJavaScript(''' // 发送当前URL到Flutter的方法 function sendUrl() { window.parent.postMessage('URL_UPDATE:' + window.location.href, '*'); } // 页面加载完成时发送初始URL window.addEventListener('load', sendUrl); // 监听浏览器前进后退 window.addEventListener('popstate', sendUrl); // 监听哈希路由变化 window.addEventListener('hashchange', sendUrl); // 拦截window.location.href跳转 const originalHrefSetter = Object.getOwnPropertyDescriptor(window.location, 'href').set; Object.defineProperty(window.location, 'href', { set: function(val) { originalHrefSetter.call(this, val); setTimeout(sendUrl, 100); // 延迟确保URL已更新 } }); '''); } void _updateUrl(String url) { if (mounted) setState(() => _currentUrl = url); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('当前URL: $_currentUrl')), body: WebViewWidget(controller: _controller), ); } }
注意事项:
- 方案二中的JS代码需根据目标页面的路由机制调整,比如单页应用可能需要额外监听框架自带的路由事件(如React Router的
history.listen) - 使用
postMessage时建议指定具体的源(替换*),避免安全风险
内容的提问来源于stack exchange,提问作者Samir
相关产品推荐
相关产品推荐

