javascript – WKScriptMessageHandler不会在网页上的按钮元素上收听“onclick”或“click”事件.该网页使用Reactjs开发

前端之家收集整理的这篇文章主要介绍了javascript – WKScriptMessageHandler不会在网页上的按钮元素上收听“onclick”或“click”事件.该网页使用Reactjs开发前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在UIViewController的视图中使用WKWebView来显示使用url端点托管在服务器上的网页.该网页使用Reactjs.这就是我对网页的所有信息.代码创建webview并将webview作为控制器视图的子视图插入.
let requestObj = URL(string:urlString)!
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
webViewWK = WKWebView(frame: .zero,configuration: configuration)
webViewWK.navigationDelegate = self
_ = webViewWK.load(requestObj)
webViewwrapper = WKWebViewWrapper(forWebView: webViewWK)

网页加载正常,控制器也充当webview的委托,并接收相同的消息.现在我还实现了一个符合WKScriptMessageHandler的WKWebViewWrapper类.然后,此类可以从Webkit对象接收消息,该消息由WKWebView创建的场景创建.实现方法如下

class WKWebViewWrapper : NSObject,WKScriptMessageHandler{

var wkWebView : WKWebView
let eventNames = ["buttonClick"]
var eventFunctions: Dictionary<String,(String) -> Void> = [:]
let controller: WKUserContentController

init(forWebView webView : WKWebView){
    wkWebView = webView
    controller = WKUserContentController()
    super.init()
}

func userContentController(_ userContentController: WKUserContentController,didReceive message: WKScriptMessage) {
    if let contentBody = message.body as? String {
        if let eventFunction = eventFunctions[message.name]{
            print("Detected javascript event")
        }
    }
}

func setUpPlayerAndEventDelegation(){
    wkWebView.configuration.userContentController = controller
    for eventname in eventNames {
        controller.add(self,name: eventname)
        eventFunctions[eventname] = { _ in }

        wkWebView.evaluateJavaScript("var elements = document.getElementsByClassName('btn button_btn button_primary button_md button_block'); for (var i = 0 ; i < elements.length; i++) { elements[i].addEventListener('onClick',function(){ window.webkit.messageHandlers.\(eventname).postMessage(JSON.stringify(isSuccess)) }); }") { any,error in
            if let error = error {
                print("EvaluateJavaScript Error:",error)
            }

            if let any = any {
                print("EvaluateJavaScript anything:",any)
            }

        }
    }
}

}

setUpPlayerAndEventDelegation()方法是最重要的部分.这里为WKUserContentController类型的控制器对象使用其add(:,name :)方法添加消息处理程序.根据文档,此方法将name参数的messageHandler添加到webkit对象.当触发消息处理程序时,将使用有用的参数调用WKScriptMessageHandler的userContentController(userContentController:WKUserContentController,didReceive message:WKScriptMessage)方法.然后我使用webview的evaluateJavaScript方法将javascript注入网页,如下所示

var elements = document.getElementsByClassName('btn button_btn button_primary button_md button_block'); 
for (var i = 0 ; i < elements.length; i++) {
    elements[i].addEventListener('onClick',function(){ window.webkit.messageHandlers.\(eventname).postMessage(JSON.stringify(true)) }); 
}

它使用给定的类获取元素.然后我遍历数组,为每个元素的HTML事件’onClick’添加事件监听器.对于事件监听器,我添加了一个匿名函数来触发webkit上先前注册的消息处理程序.这个脚本正确执行,因为我没有在evaluateJavaScript方法的完成块中得到错误.所以我现在可以肯定,当一个按钮onClick HTML事件发生时,将执行匿名函数,而后者将为webkit对象上的messageHandler执行postMessage.

现在我从WKWebViewDelegate方法webView(_ webView:WKWebView,didFinish navigation:WKNavigation!)调用WKWebViewWrapper的setUpPlayerAndEventDelegation()方法,在那里我可以确保通过comapring WKNavigation对象来加载所有HTML元素.

流程执行,在页面加载后,我点击任何按钮,我的脚本消息处理程序,即WKWebViewWrapper类,都没有观察到事件.方法userContentController(_ userContentController:WKUserContentController,didReceive message:WKScriptMessage)根本没有被触发.

这里有什么我想念的吗?我不擅长Javascript.如果Reactjs需要一些不同的脚本和事件监听器的按钮元素,请告诉我. I have reffered this tutorial.

PS:如果我们在已加载页面的webbrowser上添加类似的脚本输出控制台消息,它可以正常工作.

解决方法

请注意0​​7000中有关WKWebViewConfiguration的重要行为(但鲜为人知),

WKWebViewConfiguration仅在首次初始化Web视图时使用.创建后,您无法使用此类更改Web视图的配置.

因此,通常您应该在创建Web视图之前完全设置WKUserContentController.

// First,create custom configuration with user script
let userController = WKUserContentController()
let scalingScriptString = "var Meta = document.createElement('Meta'); Meta.setAttribute('name','viewport'); Meta.setAttribute('content','width=device-width'); document.getElementsByTagName('head')[0].appendChild(Meta);";
let scalingScript = WKUserScript(source: scalingScriptString,injectionTime: .atDocumentStart,forMainFrameOnly: true)
userController.addUserScript(scalingScript)

let configurations = WKWebViewConfiguration()
configurations.userContentController = userController  // MUST set controller in configurations before creating webview
// Now,use that configuration to create the webview
webView = WKWebView(frame: .zero,configuration: configurations)

猜你在找的JavaScript相关文章