You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:30:58