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

React多iframe(PDF预览)点击事件监听方案技术问询

React函数式组件中监听iframe点击事件的解决方案

在React函数式组件中通过iframe展示多份发票PDF时,需要实现iframe的点击事件监听。最初采用基于window blur事件的方案检测点击,但存在以下问题:

  • 仅能检测单次点击,后续点击无法触发;
  • 无法识别被点击的具体iframe实例;
  • 在useEffect中绑定window事件监听器时出现依赖警告,实现方式存疑。

尝试通过mouseOver事件记录当前iframe,但blur函数无法获取更新后的状态值。最终借助useCallback等Hook解决了所有问题,完整可行的组件代码如下:

import "./Matching.css"
import { useState, useEffect, useCallback } from 'react';
import axios from 'axios'; // 补充原代码缺失的axios导入

const Matching = () => {
    const [filelist, setFilelist] = useState([])
    const [state, setState] = useState({ iframeMouseOver: false }) // 修正初始值为对象,更符合业务逻辑
    const [pdfFrame, setPdfFrame] = useState(null)

    const mandant = 2;


    useEffect(() => {
        /* 仅在组件加载时获取文件列表,因此依赖项为空数组
           需在public文件夹中创建对应目录并放入PDF文件,示例数据格式:
        {
            "file_path": "./view/public/files/2/8dc9e7a05ad84f0bd675624416f7c308.pdf",
            "file_path_fe": "./files/2/8dc9e7a05ad84f0bd675624416f7c308.pdf",
            "hash": "8dc9e7a05ad84f0bd675624416f7c308",
            "id": 1,
            "mandant": "2",
            "name": "Satzung.pdf",
            "org_name": "Satzung.pdf",
            "size": 126286,
            "type": "application/pdf"
        }
        */
        axios.post("/select", {
            "table": "files",
            "columns": ["*"],
            "where": `where mandant = ${mandant}`
        }).then(res => setFilelist(res.data))
    }, [])

    const onblur = useCallback(() => {
        if (state.iframeMouseOver) {
            setTimeout(() => {
                window.focus();
                // 此处可添加点击iframe后的业务逻辑,比如打印当前选中的文件信息
                console.log("点击了目标iframe:", pdfFrame);
            }, 0);
        }
    }, [pdfFrame, state.iframeMouseOver]);

    useEffect(() => {
        // 初始化时聚焦页面,确保blur事件能正确触发
        window.focus();
        // 添加window blur事件监听
        window.addEventListener("blur", onblur);

        // 组件卸载时清理事件监听,避免内存泄漏
        return () => {
            window.removeEventListener("blur", onblur);
        }
    }, [onblur]);


    const handleOnMouseOver = (e) => {
        setPdfFrame(e.currentTarget.querySelector('iframe'))
        setState({ iframeMouseOver: true });
    };

    const handleOnMouseOut = (e) => {
        setPdfFrame(null)
        setState({ iframeMouseOver: false });
        window.focus(); // 鼠标移出时将焦点切回页面,确保后续blur事件正常触发
    };

    return (
        <div className="matching-wrapper">
            <div className="row">
                <div className="col-3">
                    {filelist?.map((element, index) => (
                        <div key={element.id || index} id={`${index}_pdf`}
                            onMouseOver={handleOnMouseOver}
                            onMouseOut={handleOnMouseOut}
                        >
                            <iframe 
                                title={`pdf_viewer_${element.id || index}`} 
                                src={element.file_path_fe} 
                                width="100%" 
                                height="400em" 
                            />
                        </div>
                    ))}
                </div>
                <div className="col-2">
                    {/* 其他无关内容 */}
                </div>
                <div className="col-7">
                    {/* 其他无关内容 */}
                </div>
            </div>
        </div >
    );
};

export default Matching;

关键解决点说明

  1. 用useCallback包裹onblur函数:确保函数能捕获到最新的pdfFrame和state.iframeMouseOver状态值,同时消除useEffect的依赖警告。
  2. 通过mouseOver/mouseOut追踪当前hover的iframe:鼠标悬停时记录目标iframe实例,移出时清空状态,结合blur事件判断是否点击了iframe。
  3. 每次blur后重新聚焦页面:保证后续点击iframe时能再次触发window blur事件,解决单次点击失效的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:23:23