我想在iframe上存档onClick事件,我使用该iframe来显示不同的发票pdf.
为此,我使用了filmix:
const [filelist, setFilelist] = useState([])
{filelist?.map((element, index) => (
<div key={index} id={index + "_pdf"}
onMouseOver={(e) => handleOnMouseOver(e)}
onMouseOut={(e) => handleOnMouseOut(e)}
>
{<iframe title="pdf_viewer" src={`${element.file_path_fe}`} width="100%" height="400em" />}
</div>
))}
Now I've found this snippet:
https://codesandbox.io/p/sandbox/react-detect-mouse-click-over-iframe-708ys?file=%2Fsrc%2FApp.js%3A21%2C4
where clicks are detected via the blur effect.
Since I use functional components, I have rewritten it this way:
useEffect(() => {
...
// iframe clickable:
// Focus the page
window.focus();
// Add listener to check when page is not focussed
// (i.e. iframe is clicked into)
window.addEventListener("blur", onblur);
return () => {
// Anything in here is fired on component unmount.
// so clean up the window eventlistener
window.removeEventListener("blur", onblur);
}
// remove onblur missing dependency warning
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
以及功能:
const onblur = (e) => {
if (state) {
//window.focus();
console.log(e);
}
};
const handleOnMouseOver = (e) => {
console.log("mouse in");
setState({ iframeMouseOver: true });
};
const handleOnMouseOut = (e) => {
console.log("mouse out");
window.focus(); // Make sure to set focus back to page
setState({ iframeMouseOver: false });
};
它有效,但这并不完全是我想要的方式. 所以我的问题是:
- 它正确检测点击,但一次只能检测一次.之后,点击就会被忽略. 我曾try 重新聚焦窗口,希望在再次单击时重新触发模糊事件,但这不起作用. 我可以做些什么来存档和跟踪多次点击?
- 如果我点击当前Iframe,如何检测它? e.target仍然检测到它看起来的窗口. 由于我有多个pdf,所以我想获取我点击的当前pdf.
- 在useEffect挂钩中添加窗口. eventSYS是正确的方法吗?由于onblur功能存在警告.
Edit: 我有一个关于如何跟踪当前iframe的 idea ,我完全忘记了我有mouseOver事件. 我添加了一个变量:
const [pdfFrame, setPdfFrame] = useState([])
并在mouseOver事件中设置变量:
const handleOnMouseOver = (e) => {
setPdfFrame([e.target])
setState({ iframeMouseOver: true });
};
const handleOnMouseOut = (e) => {
window.focus(); // Make sure to set focus back to page
setPdfFrame([])
setState({ iframeMouseOver: false });
};
但出于某种原因,模糊函数总是显示空变量,即使它是用正确的值重新渲染的:
console.log("Rendering with: ", pdfFrame);
const onblur = () => {
if (state) {
window.focus();
console.log(pdfFrame);
}
};
我认为这是正确的方法,但我在这里错过了一些东西.
Edit2: 感谢Lanre,我让它开始工作,这是完整的组件(没有不相关的东西):
import "./Matching.css"
import { useState, useEffect, React, useCallback } from 'react';
const Matching = () => {
const [filelist, setFilelist] = useState([])
const [state, setState] = useState([{ iframeMouseOver: false }])
const [pdfFrame, setPdfFrame] = useState(null)
const mandant = 2;
useEffect(() => {
/* here set the filelist, but only once on loading thus the []
Create an file folder in public folder and add the pdf with this name(or any other name, and adjust the json)
example:
{
"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))
}, [])
//var markedRows = []
const onblur = useCallback(() => {
if (state.iframeMouseOver) {
setTimeout(() => {
window.focus();
}, 0);
}
}, [pdfFrame, state.iframeMouseOver]);
// componentDidMount equivalent
useEffect(() => {
// iframe clickable:
// Focus the page
window.focus();
// Add listener to check when page is not focussed
// (i.e. iframe is clicked into)
window.addEventListener("blur", onblur);
//console.log(pdfFrame);
return () => {
// Anything in here is fired on component unmount.
// so clean up the window eventlistener
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(); // Make sure to set focus back to page
};
return (
<div className="matching-wrapper">
<div className="row">
<div className="col-3">
{filelist?.map((element, index) => (
<div key={index} id={index + "_pdf"}
onMouseOver={(e) => handleOnMouseOver(e)}
onMouseOut={(e) => handleOnMouseOut(e)}
>
{<iframe title="pdf_viewer" src={`${element.file_path_fe}`} width="100%" height="400em" />}
</div>
))}
</div>
<div className="col-2">
{/* other stuff not relevant to the question*/}
</div>
<div className="col-7">
{/* other stuff not relevant to the question*/}
</div>
</div>
</div >
);
};
export default Matching;