如何在JS中监听window变量变化时触发回调(React场景)
解决方法
不需要轮询的话,有两种靠谱的方案,看你能不能协调原生端配合:
方案一:给window.x添加监听(纯JS端实现)
利用Object.defineProperty给window.x设置自定义的getter和setter,当原生修改x的值时,setter会自动触发,这时你就能在回调里更新React状态,触发组件重渲染。
示例代码:
import { useState, useEffect } from 'react'; function WebViewComponent() { const [xValue, setXValue] = useState(window.x); useEffect(() => { // 保存原始的x值 let currentX = window.x; // 重新定义window.x的getter和setter Object.defineProperty(window, 'x', { get() { return currentX; }, set(newVal) { if (newVal !== currentX) { currentX = newVal; // 更新React状态,触发重渲染 setXValue(newVal); // 这里可添加自定义回调逻辑 console.log('window.x已更新:', newVal); } }, configurable: true // 允许后续重新定义,避免冲突 }); // 组件卸载时恢复原始window.x return () => { delete window.x; window.x = currentX; }; }, []); return <div>当前x的值:{xValue}</div>; }
方案二:原生端主动通知(需要原生配合)
让Android/iOS在修改window.x之后,主动调用WebView中的JS方法通知前端。最常用的是window.postMessage,React端监听这个消息事件即可。
React端代码:
import { useState, useEffect } from 'react'; function WebViewComponent() { const [xValue, setXValue] = useState(window.x); useEffect(() => { const handleMessage = (event) => { // 验证消息类型(可选,提升安全性) if (event.data.type === 'xUpdated') { const newX = event.data.value; setXValue(newX); // 执行自定义回调逻辑 console.log('收到原生通知,x已更新:', newX); } }; window.addEventListener('message', handleMessage); return () => { window.removeEventListener('message', handleMessage); }; }, []); return <div>当前x的值:{xValue}</div>; }
原生端示例:
- Android(Kotlin):
webView.evaluateJavascript(""" window.postMessage({ type: 'xUpdated', value: $newXValue }, '*'); """.trimIndent(), null)
- iOS(Swift):
webView.evaluateJavaScript(""" window.postMessage({ type: 'xUpdated', value: \(newXValue) }, '*'); """) { _, error in if let error = error { print("通知前端失败:\(error)") } }
方案对比
- 方案一纯前端实现,不需要改原生代码,但如果原生用特殊方式修改
x(比如直接替换window对象),可能会绕过setter(这种情况极少)。 - 方案二更可靠,原生主动触发不会有遗漏,但需要原生开发配合修改代码。
内容的提问来源于stack exchange,提问作者Amartya Mishra
相关产品推荐
相关产品推荐

