WKWebView 加载 Uni-App 导出的本地 H5:我的开发实战经验

作为一名前端开发者,我最近在项目中遇到了一个非常有趣的挑战:如何使用 WKWebView 加载由 Uni-App 导出的本地 H5 文件。这个任务听起来并不复杂,但在实际操作过程中却遇到了不少坑。今天,我就来分享一下我的实战经验,希望能帮助到正在为此困扰的小伙伴们。


一、为什么选择 WKWebView?


首先,让我们来聊聊为什么选择了 WKWebView。WKWebView 是苹果官方推出的用于加载网页内容的控件,相比传统的 UIWebView,它具有更好的性能和更丰富的功能。尤其是在处理复杂的 H5 页面时,WKWebView 的表现更加出色。此外,WKWebView 还支持更多的 Web 标准,能够更好地兼容现代浏览器的功能。


在我们的项目中,Uni-App 是我们选择的跨平台开发框架。Uni-App 可以将同一个代码库编译成多个平台的应用,包括 iOS、Android 和 H5。而我们需要做的,就是将 Uni-App 编译生成的 H5 文件加载到 iOS 应用中,这就需要用到 WKWebView 了。


二、遇到的第一个问题:文件路径


当我开始着手这个任务时,第一个遇到的问题就是如何正确设置 H5 文件的路径。Uni-App 导出的 H5 文件是存放在本地的,而 WKWebView 默认是加载网络资源的。因此,我们需要将本地的 H5 文件转换为可以被 WKWebView 识别的 URL。


经过一番摸索,我发现可以通过 file:// 协议来访问本地文件。具体来说,我们需要获取 H5 文件所在的目录路径,并将其拼接成一个完整的 URL。例如:


let filePath = Bundle.main.path(forResource: "index", ofType: "html")
let url = URL(fileURLWithPath: filePath!)
webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())

这段代码的作用是获取 index.html 文件的路径,并将其加载到 WKWebView 中。需要注意的是,allowingReadAccessTo 参数是为了确保 WKWebView 能够读取 H5 文件中的其他资源,比如 CSS 和 JS 文件。


三、遇到的第二个问题:CSS 和 JS 文件的加载


解决了文件路径的问题后,接下来遇到的是 CSS 和 JS 文件的加载问题。虽然我们已经成功加载了 index.html,但页面的样式和交互功能并没有正常显示。经过调试,我发现这是因为 H5 文件中的相对路径没有正确解析。


原来,Uni-App 导出的 H5 文件中,CSS 和 JS 文件的引用路径是相对的,而我们在加载本地文件时,需要将这些路径转换为绝对路径。为了解决这个问题,我尝试了几种方法:


  • 方法一:修改 H5 文件中的路径
    最直接的方法是手动修改 H5 文件中的路径,将其改为绝对路径。不过这种方法比较繁琐,尤其是当项目中有大量文件时,逐个修改会非常耗时。
  • 方法二:使用 base 标签
    另一种方法是在 index.html 中添加 <base href="."> 标签,这样可以让所有的相对路径都相对于当前文件所在的目录。这种方法简单有效,但也有一些局限性,比如可能会导致某些第三方库的路径出现问题。
  • 方法三:使用 WKUserScript
    最终,我选择了使用 WKUserScript 来动态修改 H5 文件中的路径。通过在 WKWebView 中注入一段 JavaScript 代码,可以在页面加载时自动将所有相对路径转换为绝对路径。这样既不需要修改源文件,也不会影响第三方库的正常使用。

以下是我在项目中使用的 WKUserScript 代码:


let scriptSource = "")(function() {
var base = document.location.href;
var links = document.querySelectorAll('link, script');
for (var i = 0; i < links.length; i++) {
var link = links[i];
if (link.src || link.href) {
var url = new URL(link.src || link.href, base);
link.src = url.href;
link.href = url.href;
}
}
})();"
let userScript = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
webView.configuration.userContentController.addUserScript(userScript)

这段代码的作用是在页面加载完成后,遍历所有的 linkscript 标签,将它们的 srchref 属性转换为绝对路径。这样一来,所有的 CSS 和 JS 文件都能正常加载了。


四、遇到的第三个问题:与原生应用的交互


解决了 CSS 和 JS 文件的加载问题后,接下来要解决的是 H5 页面与原生应用的交互问题。Uni-App 提供了一些内置的 API,可以方便地实现 H5 与原生应用之间的通信。然而,在使用 WKWebView 时,这些 API 并不能直接使用,因为它们依赖于特定的环境。


为了实现 H5 与原生应用的交互,我使用了 WKScriptMessageHandler。通过在 H5 页面中调用 window.webkit.messageHandlers,可以向原生应用发送消息;而在原生应用中,可以通过实现 WKScriptMessageHandler 协议来接收并处理这些消息。


以下是我在 H5 页面中使用的 JavaScript 代码:


if (window.webkit && window.webkit.messageHandlers) {
window.webkit.messageHandlers.native.postMessage({
action: 'showToast',
message: 'Hello from H5!'
});
}

而在原生应用中,我实现了 WKScriptMessageHandler 协议,并在 userContentController(_:didReceive:) 方法中处理收到的消息:


extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if let body = message.body as? [String: Any], let action = body["action"] as? String {
switch action {
case "showToast":
if let message = body["message"] as? String {
print("Received message from H5: \(message)")
// 在这里可以调用原生的 Toast 组件
}
default:
break
}
}
}
}

通过这种方式,H5 页面可以轻松地与原生应用进行交互,实现了无缝的用户体验。


五、总结与展望


经过几天的努力,我终于成功实现了 WKWebView 加载 Uni-App 导出的本地 H5 文件,并解决了其中遇到的各种问题。这次经历让我对 WKWebView 和 Uni-App 的结合有了更深的理解,也积累了不少宝贵的经验。


在未来的工作中,我将继续探索更多关于 H5 与原生应用交互的技术,争取为用户提供更好的体验。如果你也在做类似的工作,欢迎在评论区留言交流,大家一起进步!

点赞(0)

评论列表 共有 0 条评论

暂无评论
立即
投稿
发表
评论
返回
顶部