WKWebView捕获JS Error 跨域解决

探讨UIWebView和WKWebView在处理跨域JS错误时的问题与解决方案,包括如何配置允许跨域访问,以及在跨域环境下正确捕获JS错误的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过window.onerror捕获到js error以后,发现js error都是Script error,毫无参考价值,webkit源码查看可知,script资源加载的地方,是进行了同源策略判断的,如果是非同源资源,errorMessage就被写死了Script error
在这里插入图片描述

File跨域漏洞

UIWebView虽然已经被遗弃,但依然还有很多app继续使用,且最新版本的iOS也会兼容UIWebView。由于UIWebView本身存在严重的跨域漏洞,所以只要使用UIWebView都有可能存在跨域漏洞。漏洞原因在于UIWebView的WebKitAllowUniversalAccessFromFileURLs和WebKitAllowFileAccessFromFileURLs默认开启,导致通过js可以访问沙箱内的文件,甚至可以静默上传文件到远端。

WKWebView默认allowFileAccessFromFileURLs和allowUniversalAccessFromFileURLs选项为false,但如果开发者开启了这两个API,同样存在跨域漏洞。但是如果开启了这两个API,我们就可以让WKWebView支持跨域JS Error的捕获,代码如下所示:

//存在跨域漏洞
[configuration setValue:@TRUE forKey:@"allowUniversalAccessFromFileURLs"];
[configuration.preferences setValue:@"TRUE" forKey:@"allowFileAccessFromFileURLs"] ;

但是在这样的情况下,也会存在毫无参考价值的Script error,我理解是因为虽然WKWebView支持了跨域JS Error捕获,但是本身的js资源也要支持跨域,静态资源请求需要加多一个Access-Control-Allow-Origin头部,同时script引入外链的标签需要加多一个crossorigin的属性

参考文章

1、https://www.baidufe.com/item/7ee009bfbcd0fe94bd3e.html
2、https://www.cnblogs.com/cathsfz/p/how-to-capture-and-analyze-javascript-error.html
3、https://stackoverflow.com/questions/50229935/wkwebview-get-javascript-errors
4、https://mabin004.github.io/2018/06/25/iOS%E5%BA%94%E7%94%A8%E6%B2%99%E7%AE%B1/
5、http://rapheal.sinaapp.com/2014/11/06/javascript-error-monitor/

<?php // 设置时区为北京时间 date_default_timezone_set('Asia/Shanghai'); // 设置内容类型和编码 header('Content-Type: text/html; charset=utf-8'); // 移除X-Frame-Options,避免拦截iframe加载 header_remove('X-Frame-Options'); // 【临时注释掉 Content-Security-Policy】 header("Content-Security-Policy: frame-ancestors 'self' https://e.hzcl.org.cn"); // 禁止缓存,方便调试 header('Cache-Control: no-store, no-cache, must-revalidate'); header('Pragma: no-cache'); // 限制脚本最大执行时间,防止死循环卡死 set_time_limit(5); // 关闭错误显示,避免页面错乱 ini_set('display_errors', 0); error_reporting(0); // 清空输出缓冲 while (ob_get_level()) { ob_end_clean(); } ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <title>移动App WebView 测试页面</title> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> <style> body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 20px; line-height: 1.6; background-color: #fafafa; color: #333; } </style> </head> <body> <h1>移动App WebView测试页面</h1> <p>欢迎使用移动App环境中的WebView测试页面。</p> <p>允许来自 https://e.hzcl.org.cn 的页面以iframe形式嵌入。</p> <p>当前服务器时间:<?= date('Y-m-d H:i:s') ?></p> <script> console.log("页面已加载:移动App WebView测试页面"); setTimeout(() => { document.body.style.backgroundColor = "#e0f7fa"; const p = document.createElement("p"); p.textContent = "动态内容:页面渲染正常。"; document.body.appendChild(p); }, 1000); </script> </body> </html> 安卓能访问,为啥苹果不能访问
06-25
<think>好的,我现在需要解决用户提出的关于uni-app中web-view组件htmlPath为空导致显示“路径加载中”的问题。用户之前已经提供了一个详细的解决方案,但可能还存在一些疑问或需要更具体的指导。 首先,回顾用户的问题,他们在onLoad生命周期中设置了htmlPath,但console输出的最终路径为空,导致web-view无法加载内容。用户希望了解如何正确赋值htmlPath以避免这个问题。 我需要先理解uni-app中web-view的工作原理。web-view的src属性需要正确的路径来加载本地或远程的HTML文件。路径错误或未正确初始化会导致加载失败。根据用户提供的代码示例,他们在H5和APP-PLUS环境下有不同的路径设置,特别是Android需要添加_www前缀。 接下来,用户可能遇到的常见问题包括:条件编译未正确使用、路径拼写错误、静态文件位置不正确、平台差异处理不当等。需要逐一排查这些可能性。 首先检查数据初始化。确保htmlPath在data中正确初始化为空字符串,这可以避免undefined的问题。然后验证onLoad生命周期钩子是否正确触发,确保路径赋值逻辑在页面加载时执行。 平台判断是否正确使用条件编译。H5和APP-PLUS需要不同的路径处理,特别是在Android上需要添加_www前缀。用户提供的代码已经做了平台判断,但可能在实际项目中由于条件编译错误导致路径未被正确赋值。需要确认代码中的条件编译指令是否正确,比如#ifdef H5和#ifdef APP-PLUS是否包裹了对应的逻辑。 静态文件的存放位置也很重要。在uni-app中,static目录是默认的静态资源目录,所有放在这里的文件会被直接复制到打包后的目录中。需要确认HTML文件是否放置在static目录下,并且路径是否正确。例如,如果HTML文件在static/demo.html,那么在代码中应该引用“/static/demo.html”(H5)或“_www/static/demo.html”(Android APP)。 控制台日志的输出是关键,用户提到console.log显示路径为空,这说明赋值逻辑可能没有执行。需要检查条件编译是否生效,可能用户没有正确配置编译环境,或者在错误的平台下运行代码。例如,在H5环境下运行APP-PLUS的代码会导致路径未被赋值。 另外,路径字符串的拼写是否正确,比如是否漏写了斜杠或文件名错误。例如,“static/demo.html”和“static\demo.html”在不同平台下可能会有不同的解析方式,应该统一使用正斜杠。 还有可能是生命周期钩子的执行顺序问题,比如在onLoad中赋值,但页面渲染时htmlPath还未被正确设置,导致web-view组件接收到空值。可以尝试在赋值后强制更新视图,或者使用v-if条件渲染,确保htmlPath有值后再渲染web-view组件。 此外,用户可能没有考虑到不同平台下的路径基准。在H5环境下,路径是相对于项目的根目录,而在APP-PLUS中,路径是相对于应用的安装目录。特别是在Android平台上,打包后的资源会被放在_www目录下,因此路径需要加上这个前缀。 最后,可能需要检查uni-app的版本和运行环境是否存在已知的bug,或者是否有配置错误导致静态资源未被正确打包。 总结来说,解决方案应包括:验证数据初始化和生命周期钩子、检查条件编译和平台路径处理、确认静态文件位置和路径拼写正确、通过日志调试路径赋值过程,以及使用v-if确保路径有效后再渲染web-view组件。</think>### 解决 UniApp WebView `htmlPath` 为空导致显示“路径加载中”的完整方案 若 `htmlPath` 未正确赋值导致 `<web-view>` 组件持续显示“路径加载中”,核心问题通常源于 **平台路径规则未适配** 或 **条件编译失效**。以下是分步骤的排查与修复指南: --- #### 一、基础路径配置验证 ##### 1. **静态文件存放位置** 确保 HTML 文件存放在项目根目录的 `static` 文件夹内,路径层级与代码完全一致: ```text 项目结构: ├─static │ └─demo.html // ✅ 正确路径:static/demo.html │ └─subdir/page.html // ❌ 错误示例:static/subdir/page.html(需调整代码路径或移动文件) ``` ##### 2. **平台路径规则** 不同平台的路径基准不同: - **H5 环境**:使用绝对路径 `/static/demo.html`(以 `/` 开头)[^1] - **Android APP**:需添加 `_www/` 前缀,即 `_www/static/demo.html` - **iOS APP**:直接使用 `static/demo.html` --- #### 二、关键代码修正 ##### 1. **严格隔离平台逻辑** 使用条件编译指令确保代码仅在目标平台执行: ```vue <script> export default { onLoad() { // #ifdef H5 this.htmlPath = "/static/demo.html"; // H5绝对路径 // #endif // #ifdef APP-PLUS const os = plus.os.name.toLowerCase(); this.htmlPath = os === "android" ? "_www/static/demo.html" : "static/demo.html"; // #endif console.log("当前路径:", this.htmlPath); // ✅ 必须验证输出 } }; </script> ``` ##### 2. **添加加载状态兜底** 通过 `v-if` 控制组件渲染时机,避免空路径闪屏: ```vue <template> <view class="container"> <web-view :src="htmlPath" v-if="htmlPath" @error="handleWebViewError" /> <view v-else class="loading-text">正在加载页面资源...</view> </view> </template> ``` --- #### 三、高频问题场景与修复 ##### 场景 1:条件编译未生效 **现象**:所有平台均未赋值路径,控制台无日志输出 **根因**:未正确使用 `#ifdef` 或编译目标选择错误 **修复**: - 检查 `manifest.json` ➔ 确保已勾选 H5/APP 模块 - 运行命令明确指定平台: ```bash # H5 调试 npm run dev:h5 # Android 调试 npm run dev:app-plus --platform android ``` ##### 场景 2:Android 路径缺少 `_www/` **现象**:Android 真机白屏,控制台报 `net::ERR_FILE_NOT_FOUND` **根因**:未适配 Android 资源目录映射规则 **修复**: ```javascript // #ifdef APP-PLUS this.htmlPath = plus.os.name === "Android" ? "_www/static/demo.html" : "static/demo.html"; // #endif ``` ##### 场景 3:H5 生产环境路径错误 **现象**:开发环境正常,打包后 H5 页面 404 **根因**:未使用绝对路径或服务器路由配置冲突 **修复**: ```javascript // #ifdef H5 // 正确:以 / 开头的绝对路径 this.htmlPath = "/static/demo.html"; // 错误:相对路径导致生产环境解析失败 // this.htmlPath = "static/demo.html"; // #endif ``` --- #### 四、真机调试与错误捕获 ##### 1. **控制台日志分析** - **H5 环境**:浏览器开发者工具 ➔ Console 面板 ➔ 检查 `htmlPath` 输出值 - **APP 环境**: - Android:Android Studio ➔ Logcat ➔ 过滤 `WebView` 相关日志 - iOS:Xcode ➔ 控制台 ➔ 搜索 `WKWebView` 错误 ##### 2. **错误监听回调** 添加 WebView 错误事件捕获: ```vue <script> export default { methods: { handleWebViewError(e) { console.error("WebView加载失败:", e.detail); uni.showToast({ title: "页面加载失败,请检查网络或文件路径", icon: "none" }); } } }; </script> ``` --- #### 五、完整可运行代码 ```vue <template> <view class="container"> <web-view :src="htmlPath" v-if="htmlPath" @error="handleWebViewError" /> <view v-else class="loading-wrapper"> <text class="loading-text">资源加载中...</text> <uni-icons type="spinner-cycle" size="20" color="#666" /> </view> </view> </template> <script> export default { data() { return { htmlPath: "" // 初始化为空 }; }, onLoad() { // 平台判断 // #ifdef H5 this.htmlPath = "/static/demo.html"; // H5绝对路径 // #endif // #ifdef APP-PLUS const os = plus.os.name.toLowerCase(); this.htmlPath = os === "android" ? "_www/static/demo.html" : "static/demo.html"; // #endif console.log("WebView路径:", this.htmlPath); // 必须验证 }, methods: { handleWebViewError(e) { console.error("加载失败:", e.detail); } } }; </script> <style> .container { height: 100vh; } .loading-wrapper { display: flex; justify-content: center; align-items: center; height: 100%; } .loading-text { margin-right: 8px; color: #666; } </style> ``` --- ### 相关问题 1. **WebView 如何与 UniApp 页面实现双向通信?** *答:通过 `uni.postMessage` 发送消息,HTML 中使用 `window.addEventListener('message')` 接收,反之通过 `uni.$emit` 触发原生事件[^2]。* 2. **如何动态修改 WebView 加载的 URL 参数?** *答:在路径后拼接查询字符串,如 `demo.html?userId=123`,HTML 内通过 `URLSearchParams` 解析。* 3. **Android 平台 WebView 加载本地 HTML 出现问题如何解决?** *答:使用 `file://` 协议加载本地文件时需在 `manifest.json` 中配置 `"androidWebView" : { "fileAccess": true }`[^3]。*
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值