You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS设备Safari浏览器双击无法触发JavaScript函数的解决咨询

解决iOS Safari中表格行双击事件不触发的问题

嘿,我来帮你梳理下这个问题——iOS Safari对<tr>元素的ondblclick支持确实有不少兼容性坑,尤其是这种老旧的JS驱动站点,很容易因为浏览器的默认行为(比如双击缩放优先级更高)导致事件没机会触发。既然你打算用WebKit做内置浏览器,这里有几个从简到繁的方案,你可以按需尝试:

方案1:先禁用iOS Safari的双击缩放(最快验证)

很多时候iOS的双击缩放会抢先响应,把你的双击事件给“吃掉”了。你可以先在WebKit加载页面完成后,注入一段JS来禁用缩放,看看能不能让原生的ondblclick恢复生效:

// 在WebView加载完成后执行这段JS
let disableZoomScript = """
// 阻止双指缩放
document.addEventListener('touchstart', function(e) {
  if (e.touches.length > 1) {
    e.preventDefault();
  }
}, { passive: false });

// 阻止双击缩放
let lastTouchEnd = 0;
document.addEventListener('touchend', function(e) {
  const now = Date.now();
  if (now - lastTouchEnd <= 300) {
    e.preventDefault();
  }
  lastTouchEnd = now;
}, false);
"""

// 假设你用的是WKWebView,在didFinish导航回调里注入脚本
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript(disableZoomScript, completionHandler: nil)
}

这个方案最省事,如果能解决问题就完美了。

方案2:重新绑定双击事件(更可靠的兼容方案)

如果方案1没用,那我们直接绕过原生的ondblclick绑定,用JS重新给所有表格行绑定双击事件。这样既能避开兼容性问题,还能准确拿到任务ID调用函数:

// 注入脚本重新绑定双击事件
let rebindDoubleClickScript = """
// 遍历所有带ondblclick属性的表格行
document.querySelectorAll('tr[ondblclick]').forEach(tr => {
  // 提取原ondblclick里的函数调用内容,比如openPairingDetails(12345)
  const originalHandler = tr.getAttribute('ondblclick');
  // 先移除原生属性,避免冲突
  tr.removeAttribute('ondblclick');
  
  // 绑定新的双击事件
  tr.addEventListener('dblclick', function(e) {
    // 方式1:直接执行原函数调用(简单粗暴,适合任何参数格式)
    eval(originalHandler);
    
    // 方式2:解析任务ID再调用(更安全,适合你的数字参数场景)
    // const taskMatch = originalHandler.match(/openPairingDetails\\((\\d+)\\)/);
    // if (taskMatch) {
    //   const taskId = taskMatch[1];
    //   openPairingDetails(taskId);
    // }
  });
});
"""

// 同样在页面加载完成后执行
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript(rebindDoubleClickScript) { result, error in
        if let error = error {
            print("注入脚本出错:\(error.localizedDescription)")
        }
    }
}

两种执行方式选一个就行:用eval的话不用管参数格式,直接复用原代码;正则解析的话更安全,避免eval的潜在风险。

方案3:原生层拦截双击手势(最灵活的终极方案)

如果上面的JS方案还是有问题,那我们直接在WebKit的原生代码里监听双击手势,然后找到点击的表格行,提取参数后主动调用JS函数:

// 给WKWebView添加双击手势识别器
override func viewDidLoad() {
    super.viewDidLoad()
    let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(_:)))
    doubleTapGesture.numberOfTapsRequired = 2
    webView.addGestureRecognizer(doubleTapGesture)
}

@objc func handleDoubleTap(_ gesture: UITapGestureRecognizer) {
    // 将手势的屏幕坐标转换成网页内的坐标
    let screenPoint = gesture.location(in: webView)
    let webPoint = webView.convert(screenPoint, to: webView.scrollView)
    
    // 调用JS获取点击位置的表格行及其ondblclick内容
    let getTrScript = """
    function findClickedTr(x, y) {
        let element = document.elementFromPoint(x, y);
        // 向上查找最近的<tr>元素
        while (element && element.tagName !== 'TR') {
            element = element.parentElement;
        }
        return element ? element.getAttribute('ondblclick') : null;
    }
    findClickedTr(\(webPoint.x), \(webPoint.y));
    """
    
    webView.evaluateJavaScript(getTrScript) { result, error in
        guard let handlerStr = result as? String, error == nil else {
            return
        }
        // 解析任务ID并调用函数
        if let taskMatch = handlerStr.match(/openPairingDetails\\((\\d+)\\)/) {
            let taskId = taskMatch[1]
            self.webView.evaluateJavaScript("openPairingDetails(\(taskId));", completionHandler: nil)
        } else {
            // 解析失败的话直接执行原函数调用
            self.webView.evaluateJavaScript(handlerStr, completionHandler: nil)
        }
    }
}

这个方案完全绕过了网页端的事件绑定问题,直接在原生层处理双击,兼容性最好,适合复杂的动态页面场景。

额外提醒

  • 不管用哪种方案,一定要等页面完全加载完成再执行脚本或绑定手势,否则可能找不到动态生成的表格行;
  • 如果页面是AJAX动态加载表格的,你需要用MutationObserver监听DOM变化,一旦有新的表格行生成,就重新执行绑定脚本。

内容的提问来源于stack exchange,提问作者BPN

火山引擎 最新活动