Flutter WebViewPlus调用JS函数遇localStorage禁用问题求助
解决WebViewPlus中data URL下localStorage禁用的问题
错误原因
你遇到的错误根源在于:用controller.loadString()加载HTML内容时,WebView会把内容打包成data:text/html,...格式的URL,而浏览器出于安全限制,会直接禁止这类URL访问localStorage,导致第三方JS库调用存储时触发权限报错。
解决方案
方案1:将HTML存为本地资产文件加载(推荐)
这种方式彻底避开data URL的限制,是最可靠的解决办法:
- 配置项目资产声明
在项目根目录的pubspec.yaml中添加资产配置:
flutter: assets: - assets/payment_dashboard.html
- 创建本地HTML文件
在项目根目录新建assets文件夹,里面创建payment_dashboard.html文件,把你的HTML代码复制进去:
<!DOCTYPE html> <html> <head> <script src="https://bla.blabla.io/bla.js"></script> </head> <body> <div id="savingContainer"></div> <script> function myFunction() { const credentials = { token: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', } Zwitch.openSavingsAccount({ containerId: 'savingContainer', credentials: credentials, callbacks: { onSuccess: (resp) => { console.log(resp); }, onError: (resp) => { console.log(resp); }, } }); } </script> <h1>My First Heading</h1> <button onclick="myFunction()">Submit</button> </body> </html>
- 修改Dart代码加载本地资产
替换原来的loadString方式,改用initialUrl加载本地资产,同时配置Android和iOS的存储权限:
import 'package:flutter/material.dart'; import 'package:webview_flutter_plus/webview_flutter_plus.dart'; class WebViewStorage extends StatelessWidget { const WebViewStorage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: WebViewPlus( javascriptMode: JavascriptMode.unrestricted, initialUrl: 'assets/payment_dashboard.html', // Android端开启存储相关权限 androidSettings: AndroidSettings( domStorageEnabled: true, databaseEnabled: true, allowFileAccess: true, allowContentAccess: true, ), // iOS端开启存储权限 iosSettings: IosSettings( domStorageEnabled: true, sharedStorageEnabled: true, ), ), ); } }
方案2:配置WebView存储(仅作备选,可能不稳定)
如果必须用loadString加载字符串HTML,可以尝试添加存储配置,但由于data URL的固有安全限制,部分场景可能仍无法正常工作:
import 'package:flutter/material.dart'; import 'package:webview_flutter_plus/webview_flutter_plus.dart'; class WebViewStorage extends StatelessWidget { const WebViewStorage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: WebViewPlus( javascriptMode: JavascriptMode.unrestricted, // Android端配置存储 androidSettings: AndroidSettings( domStorageEnabled: true, databaseEnabled: true, allowFileAccess: true, ), // iOS端配置存储 iosSettings: IosSettings( domStorageEnabled: true, sharedStorageEnabled: true, ), onWebViewCreated: (controller) { controller.loadString('''<!DOCTYPE html> <html> <head> <script src="https://bla.blabla.io/bla.js"></script> </head> <body> <div id="savingContainer"></div> <script> function myFunction() { const credentials = { token: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', } Zwitch.openSavingsAccount({ containerId: 'savingContainer', credentials: credentials, callbacks: { onSuccess: (resp) => { console.log(resp); }, onError: (resp) => { console.log(resp); }, } }); } </script> <h1>My First Heading</h1> <button onclick="myFunction()">Submit</button> </body> </html> '''); }, ), ); } }
注意事项
- Android和iOS的WebView存储配置是独立的,两个平台都需要设置到位;
- 优先选择方案1,因为data URL的安全限制是浏览器内核的固有规则,方案2无法彻底覆盖所有场景的问题。
内容的提问来源于stack exchange,提问作者Rafi
相关产品推荐
相关产品推荐

