【问题标题】:Detect button click (by class name) in WKWebView with JavaScript.evaluate使用 JavaScript.evaluate 在 WKWebView 中检测按钮单击(按类名)
【发布时间】:2020-07-20 00:25:52
【问题描述】:

我一直在尝试为用户在 WKWebView 中单击此按钮元素时添加一个侦听器:

<div class="web-navigation__auth" data-test-web-chrome-auth="">
    <button class="web-navigation__auth-button web-navigation__auth-button--sign-in button button-reset button--auth">
        <svg ... ></path></g></svg>
        Sign In
    </button>

    <div class="web-chrome-auth-container__spinner web-chrome-auth-container__spinner--hidden"></div>
</div>

我尝试观察使用许多不同的 JavaScript 评估,并在不同的地方尝试了代码(即viewDidLoadwebView(didFinish)webView(didStartProvisionalNavigation) 等):

let js1 = "document.addEventListener('click', function(e) { e = e || window.event; if(e.target.getAttribute('class') == 'web-navigation__auth-button') { console.log(e.target.value); } });"
let js2 = "var elements = document.getElementsByClassName('web-navigation__auth'); var myFunction = function() { var attribute = this.getAttribute('web-navigation__auth-button--sign-in'); alert(attribute); }; for (var i = 0; i < elements.length; i++) { elements[i].addEventListener('click', myFunction, false); }"
let js3 = "document.addEventListener('click', getElementsByClassName('web-navigation__auth-button').onclick();"

webView.evaluateJavaScript(js) { (key, err) in
    if let err = err {
        print(err.localizedDescription)
    } else {
        print("JS: You tapped the Sign In button!")
    }
}

控制台的输出似乎只在调用webView.evaluateJavaScript 时出现,不是在按下按钮时出现。除了下面关于js3 的注释之外,我没有得到任何代码在按下按钮时触发。这是webView(didFinish) 中每个 JS 调用的控制台输出:

js1: A JavaScript exception occurred     // on webView.didFinish
     JS: You tapped the Sign In button!  // on webView.didFinish

js2: A JavaScript exception occurred     // on webView.didFinish
     JS: You tapped the Sign In button!  // on webView.didFinish

js3: A JavaScript exception occurred     // on webView.didFinish
     A JavaScript exception occurred     // on Sign In button click (fired again)

关于js3 需要注意的一点是,它会在webView.didFinish 上触发错误消息,但如果按下按钮,它也会触发错误。

所以理论上,我可以创建一个标志来检查该按钮的点击;但是,我更喜欢比这个 hacky 解决方法更具体的东西:

// Error output to console on every new page load AND "Sign In" button click
var pageLoad = false    // Page has not yet loaded, false by default

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    pageLoad = true     // Page has loaded, unless new URL detected, next error = button click!
    if webView.urlHasChanged() { pageLoad = false }
    
    let js3 = "document.getElementsByClassName('web-navigation__auth-button').onclick();"
    webView?.evaluateJavaScript(js3) { (key, err) in
    if let err = err {  
        if pageLoad {
            // Error message && pageLoad = "Sign in" button pressed: CODE HERE
        }
    }
    if pageLoad && url.hasNotChanged() { pageLoad = false }
}

【问题讨论】:

    标签: javascript ios swift macos wkwebview


    【解决方案1】:

    您可以使用WKScriptMessageHandler,而无需更改您的网站源代码。

    步骤 1。使用已注册的消息处理程序实例化您的 WKWebView 实例。

    let contentController = WKUserContentController()
    
    contentController.add(self, name: "MessageHandler")
    
    let configuration = WKWebViewConfiguration()
    configuration.userContentController = contentController
    
    let webview = WKWebView(frame: .zero, configuration: configuration)
    

    步骤 2. 注入一个监听点击事件的 JS 代码,并在点击事件到达时向上面注册的消息处理程序发送一条消息。 此代码必须在您的页面加载后执行。

    let jscode = """
    buttonSelector.addEventListener('click', function(event) {
      window.webkit.messageHandlers.MessageHandler.postMessage("clicked")
    })
    """
    webview.evaluateJavaScript(jscode) { _, _ in }
    

    第 3 步:处理应用中的传入消息

    extension YourClass: WKScriptMessageHandler {
      public func userContentController(
        _ userContentController: WKUserContentController,
        didReceive message: WKScriptMessage
      ) {
        print(message) 
      }
    }
    
    

    【讨论】:

      【解决方案2】:

      您可以通过向 userContentController 添加脚本消息处理程序并监听来实现

       func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage){}
      

      下面是完整代码

      class ViewController: UIViewController,WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler {
      
          var webView: WKWebView!
          
          override func loadView() {
              webView = WKWebView()
              webView.navigationDelegate = self
              view = webView
          }
          
          override func viewDidLoad() {
              super.viewDidLoad()
              //Fetch html
              let url = URL(fileURLWithPath: Bundle.main.path(forResource: "example", ofType: "html") ?? "")
              let config: WKWebViewConfiguration = WKWebViewConfiguration()
              // Adding a script message handler
              config.userContentController.add(self, name: "test")
              webView = WKWebView(frame: self.view.frame, configuration: config)
              webView?.navigationDelegate = self
              webView.translatesAutoresizingMaskIntoConstraints = true
              webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
              self.view.addSubview(self.webView)
              //Load html page
              self.webView?.loadFileURL(url, allowingReadAccessTo: Bundle.main.bundleURL)
          }
      
          // Delegate method on click action
          func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
              if message.name == "test", let messageBody = message.body as? String {
                  print(messageBody)
              }
          }
      
      }
      

      您可以将示例 HTML 与 javascript 一起使用,如下所示

      <div id="test" style="height: 40px; width: 100px; background-color: powderblue;">Hello</div>
      <script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
      <script type="text/javascript" src="js/platform.js"></script>
      
      <script type="text/javascript">
      document.getElementById("test").addEventListener("click", function test() {
          webkit.messageHandlers.test.postMessage("TEXT");
      });
      </script>
      

      如果您正在寻找相同的东西,请告诉我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-16
        • 1970-01-01
        • 1970-01-01
        • 2013-07-11
        • 1970-01-01
        • 2021-01-01
        相关资源
        最近更新 更多