React.js中window.onblur事件在Android WebView内未触发的问题求解
问题根因
Android WebView的事件分发逻辑和普通浏览器存在差异,单独监听window.blur不生效的核心原因如下:
- 只有WebView内部元素失焦时才会触发DOM层面的
window.blur事件,应用切后台、切换其他APP、WebView所在Activity失焦等系统级失焦场景,默认不会同步给Web内核的window对象 - 部分定制ROM的WebView对
blur事件的适配存在缺陷,触发逻辑不稳定
适配解决方案
前端代码兼容修改(无需原生端配合,兼容性最优)
放弃只依赖blur事件的写法,组合监听可见性API、焦点变化等多类事件,覆盖所有失焦场景,修改后的React代码如下:
import React,{useEffect} from 'react'; function App() { useEffect(() => { const handleBlur = () => { // 统一的失焦逻辑 alert('hello'); } // 监听页面可见性变化,Android WebView下兼容性最好,切后台、被其他页面覆盖都会触发 const handleVisibilityChange = () => { if (document.hidden) { handleBlur(); } } // 监听焦点离开整个文档的场景 const handleFocusOut = (e) => { if (e.relatedTarget === null) { handleBlur(); } } // 注册多类事件兜底 window.addEventListener('blur', handleBlur); document.addEventListener('visibilitychange', handleVisibilityChange); window.addEventListener('pagehide', handleBlur); document.addEventListener('focusout', handleFocusOut); return () => { // 清理事件监听 window.removeEventListener('blur', handleBlur); document.removeEventListener('visibilitychange', handleVisibilityChange); window.removeEventListener('pagehide', handleBlur); document.removeEventListener('focusout', handleFocusOut); }; }, []); return ( <div className="App"> </div> ); } export default App;
原生端可选配置(可进一步提升兼容性,需要修改Android项目代码)
如果有权限调整嵌入WebView的Android应用代码,可新增以下配置:
- 开启WebView基础权限,保证JS事件能正常注册:
webView.settings.apply { javaScriptEnabled = true domStorageEnabled = true }
- 重写窗口焦点变化回调,主动给Web层同步失焦事件:
webView.webChromeClient = object : WebChromeClient() { override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) if (!hasFocus) { // 主动触发Web层的window.blur事件 webView.evaluateJavascript("window.dispatchEvent(new Event('blur'))", null) } } }
- 如果测试发现alert弹窗不弹出,需要额外重写
onJsAlert回调支持JS弹窗,或者把alert逻辑换成自定义的页面内提示。
内容的提问来源于stack exchange,提问作者Pawan Khade
相关产品推荐
相关产品推荐

