WKWebView 修改 HTML 界面元素,很简单
就是加载完网页后,
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
调用方法,
webView.evaluateJavaScript(script) { result, error in }
执行下脚本,
拿到元素
window.document.querySelector("#root > div > div.top > div:nth-child(2)")
修改,比较简单,不描述
配合 Chrome 的 Copy JS Path, 挺容易的
旁边的 Chrome 控制台,调试,看效果
元素隐藏
document.querySelector("#juejin > div.view-container > main > div.view.user-view > div.major-area > div.user-info-block.block.shadow > div.action-box > div.link-box.link-box").style.display = "none";
'none'
稍微有点技术含量,是动态修改 HTML 元素
还是调用 js 脚本
关键是在,合适的时机,调用 js 脚本
现在一般的 H5 ,加载完成后,
这个方法,已经走了
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
好像还会调很多网络请求,dom 渲染
我们需要,修改的 html 元素,是后续的网络请求,才生成的。
有点技术含量了, 需要监听 H5 的网络请求
js 监听每一次的网络请求,
然后每一次,都会做我们需要的修改
可能网络请求很多,我们需要的 html 元素修改,只对应其中的一次网络请求
无关的网络请求,就是获取 html 元素,返回 null
- js 代码:
var open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
this.addEventListener("load", function() {
// 拿到元素
window.document.querySelector("#root > div.top > div > div.zc-tab-item.active");
// 操作元素
});
open.apply(this, arguments);
};
- 注入 js 代码:
let configuration = WKWebViewConfiguration()
let userContentController = WKUserContentController()
if let path = Bundle.main.path(forResource: "html", ofType: "js"){
do {
let scriptContent = try String(contentsOfFile: path)
let script = WKUserScript(source: scriptContent, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
userContentController.addUserScript(script)
} catch {
print(error)
}
}
configuration.userContentController = userContentController
webView = WKWebView(frame: rect,
configuration: configuration)
更加面向对象化
分两步,
-
监听 H5 网络请求, 然后给原生,发消息
-
原生收到了注入的 js 代码,发的消息。就执行,修改 html 元素的代码
第一步,监听 H5 网络请求变化
- js 代码:
var open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
this.addEventListener("load", function() {
var message = {"status" : this.status, "responseURL" : this.responseURL}
// callbackHandler, 是约定的方法字段
webkit.messageHandlers.callbackHandler.postMessage(message);
});
open.apply(this, arguments);
};
- 注入 js 代码:
do {
let scriptContent = try String(contentsOfFile: path)
let script = WKUserScript(source: scriptContent, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
userContentController.add(self, name: "callbackHandler")
// 添加回调
userContentController.addUserScript(script)
} catch {
print(error)
}
- 收到消息的回调函数中,去修改 html 元素
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// ...
}
第 2 步,修改 html 的元素
- 调用 js 代码,
if let path = Bundle.main.path(forResource: "htmlEdit", ofType: "js"){
do {
let scriptContent = try String(contentsOfFile: path)
webView.evaluateJavaScript(scriptContent) { result, error in
}
} catch {
print(error)
}
}
- 相关的 js 脚本,
根据自己的业务,
这里只是一个,很简单的例子
window.document.querySelector("#root > div > div.top > div.zc-tab-item.active").innerHTML = "sth";