我正在撰写Chrome扩展程序。它用于记录用户浏览网页时的行为。它通过使用Chrome content script
向客户的网页添加事件监听器来实现。
content script
中的代码如下:
var recordingEvents = ['click', 'input', 'change'];
recordingEvents.forEach(function (e) {
window.addEventListener(e, handler, true);
});
自定义页面示例:
<script>
function reload() {
var ifrw = document.getElementById("iframeResult").contentWindow;
ifrw.document.open();
ifrw.document.write("<div>abc</div>");
ifrw.document.close();
}
</script>
<body>
<input type="submit" onclick="reload();" value="Reload" />
<iframe id="iframeResult"></iframe>
</body>
它使用document.open
,document.write
来重写iframe的内容。
这是一个问题。我的事件侦听器附加到window
对象。并document.open
删除其所有事件侦听器。如下图所示。
有没有办法避免document.open
删除事件侦听器?或者观察document.open
,我可以手动重新添加听众吗?
答案 0 :(得分:0)
我发现这个问题试图解决完全相同的问题。
这是一个规范https://html.spec.whatwg.org/multipage/webappapis.html#dom-document-open,表示在document.open
当前文档被销毁并替换为新文档。我希望某些事件可以像#34; loading&#34;仍然保留,没有运气。
这是我的检测代码:
const testEventName = 'TestEvent';
let tm;
function onTestEvent() {
clearTimeout(tm);
}
function listenToTestEvent() {
document.addEventListener(testEventName, onTestEvent);
}
listenToTestEvent();
function onLostEvents() {
console.log('events are lost');
listenToTestEvent();
// DO THING HERE
}
function checkIfEventsAreLost() {
document.dispatchEvent(new CustomEvent(testEventName));
tm = setTimeout(onLostEvents);
}
new MutationObserver(checkIfEventsAreLost).observe(document, { childList: true });
重新创建文档时,childList
已更改(新的documentElement
节点),这是我考虑过检测文档替换的最佳触发器。
请注意,甚至听众也会在setTimeout(..., 0)
答案 1 :(得分:0)
这是对 @Viller's answer 为何有效的详细说明。我正在将此作为一个新答案,因为它不适合评论
TestEvent
事件是一个特殊的事件,用于监控文档中先前设置的事件何时被删除。
特别是,这说明了 document.open
的情况,它不仅从文档中删除了所有侦听器,还从窗口中删除了所有侦听器。
总体思路是为一个名为 TestEvent
的自定义事件设置一个监听器,它清除超时。仅当文档发生变异并由变异观察者触发时才会设置此类超时。
由于超时将操作安排在至少在事件循环的下一个滴答期间发生,因此可以在此之前清除此类超时,从而避免同时执行其回调。而且,由于 TestEvent
事件处理程序清除了该超时,所以清除超时的事实意味着侦听器仍处于连接状态。另一方面,如果在下一次滴答之前没有清除超时,则表示事件已被删除并且需要新的“设置”。