你能在不使用 document.write() 的情况下销毁文档元素和事件侦听器吗?
Can you destroy the document element and event listeners without using document.write()?
在下面的例子中:
- 如果您右键单击文档,它会告诉您它正在侦听。
- 如果单击 m1,它将替换文档元素,但右键单击文档仍会通知您它正在侦听。您必须在顶部附近右击,因为文档没有内容。
- 如果您单击 m2,它将覆盖文档内容,并且在顶部附近右键单击不再执行任何操作。检查开发工具中的文档,确认事件处理程序已消失。
- 按下一个按钮后,您必须再次“运行 代码片段”才能尝试下一个,因为此演示具有破坏性。
有了这个信息。是否有不同的方法来销毁文档并用新的文档替换它,以这种方式销毁事件处理程序,而不使用 document.write()
函数?
document.write()
容易出错,其用法是"strongly discouraged",但我还是希望能够销毁文档及其事件监听器。
document.addEventListener('contextmenu', function (e) {
alert('still listening');
e.preventDefault();
})
function m1() {
var doc = document.implementation.createHTMLDocument();
document.replaceChild(
document.importNode(doc.documentElement, true),
document.documentElement
);
}
function m2() {
document.close();
document.write('<html></html>');
}
<button onclick="m1()">m1</button>
<button onclick="m2()">m2</button>
明确地说,button/function“m1”没有达到我的目标,因为虽然文档元素已被替换,但出于某种原因保留了前一个文档元素的事件处理程序。我想实现 m2 实现的目标,但不使用建议反对的 document.write
和 document.close
。
附录:
这个问题完全是为了更好地理解语言的限制和实现它们的引擎。请不要试图从字里行间或解决一些替代目标。这只是一个事情是否可能的问题。
我不需要知道如何删除事件侦听器或管理事件侦听器,或删除文档的所有子元素。我想知道是否有可能销毁文档元素本身,不留下任何 <html>
标记并留下其事件侦听器的 none。 document.write()
可以做到这一点,但我只是想知道是否有其他方法可以实现这个确切的目标,而不是任何其他假定的目标。
您可以使用 document.getElementById('id-here').innerHTML = ""
,像这样:
<html id="the-website">
<body>
<input type="button" onclick="document.getElementById('the-website').innerHTML = '';" value="Don't click me plz!">
</body>
</html>
我不确定这个问题的背后是什么,但我猜,当页面中的对象和事件 re-created 时,您遇到了问题。
如果是这样的话,从MDN(https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild)中可以看出,尽管你删除了HTML上的元素,它们仍然可以在内存中保留一段时间,等待让垃圾收集器清理它们。
因此,如果您希望安全地删除一段包含事件的代码,最安全的方法是先使用您最喜欢的库(如 jQuery)或使用 DOM 删除事件通过本机 JavaScript:
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
一旦你删除了所有事件,你就可以删除所有元素,最安全的方法(从内存的角度来看)是通过一个循环,先删除内部元素,然后删除父元素,等等。
我刚刚意识到实际上你可以,而且第一个示例 m1 实际上确实替换了 documentElement 并且 删除了它的事件侦听器。有趣的是,它首先没有事件侦听器,它们在 文档本身 而不是 文档元素 上。开发人员工具(在 FireFox 中)欺骗您并将它们显示为附加到 <html>
元素,即使它们在技术上并未附加到元素。如果您修改示例以实际将事件附加到 document.documentElement
而不是文档本身,则当您单击 m1:
时事件将被禁用
document.documentElement.addEventListener('contextmenu', function (e) {
alert('still listening');
e.preventDefault();
})
function m1() {
var doc = document.implementation.createHTMLDocument();
document.replaceChild(
document.importNode(doc.documentElement, true),
document.documentElement
);
}
function m2() {
document.close();
document.write('<html></html>');
}
<button onclick="m1()">m1</button>
<button onclick="m2()">m2</button>
最初我打算说不,你不能这样做,正如用户 Livingston Samuel 在此 similar but not identical question 中所说:“你不能用 Document 替换当前文档对象或任何文档对象使用 createHTMLDocument 方法创建的对象。”
不过,坚持我原来的问题,这不是我要问的文档,而是 documentElement。所以鉴于上面修改后的代码,我会说是的,这是可能的。
有趣的是,从版本 81 开始,事件侦听器显示在 FireFox 的 html 元素上,无论它们是附加到文档对象还是 documentElement 对象。我可能希望它们会而不是在附加到 document
时根本不显示它们,或者将它们放在某个抽象对象上。 iframe 确实有一个可用的抽象对象,标签为 #document
,但它不用于此,也没有事件标签:
同样有趣的是,document.write()
实际上破坏了 document
对象上的事件,而不仅仅是 document.documentElement
。它可能在 here 的某处有记录,但我似乎找不到它。
测试后 Chrome 我注意到开发人员工具会区分附加到 documentElement 的事件:
和文档本身:
在下面的例子中:
- 如果您右键单击文档,它会告诉您它正在侦听。
- 如果单击 m1,它将替换文档元素,但右键单击文档仍会通知您它正在侦听。您必须在顶部附近右击,因为文档没有内容。
- 如果您单击 m2,它将覆盖文档内容,并且在顶部附近右键单击不再执行任何操作。检查开发工具中的文档,确认事件处理程序已消失。
- 按下一个按钮后,您必须再次“运行 代码片段”才能尝试下一个,因为此演示具有破坏性。
有了这个信息。是否有不同的方法来销毁文档并用新的文档替换它,以这种方式销毁事件处理程序,而不使用 document.write()
函数?
document.write()
容易出错,其用法是"strongly discouraged",但我还是希望能够销毁文档及其事件监听器。
document.addEventListener('contextmenu', function (e) {
alert('still listening');
e.preventDefault();
})
function m1() {
var doc = document.implementation.createHTMLDocument();
document.replaceChild(
document.importNode(doc.documentElement, true),
document.documentElement
);
}
function m2() {
document.close();
document.write('<html></html>');
}
<button onclick="m1()">m1</button>
<button onclick="m2()">m2</button>
明确地说,button/function“m1”没有达到我的目标,因为虽然文档元素已被替换,但出于某种原因保留了前一个文档元素的事件处理程序。我想实现 m2 实现的目标,但不使用建议反对的 document.write
和 document.close
。
附录:
这个问题完全是为了更好地理解语言的限制和实现它们的引擎。请不要试图从字里行间或解决一些替代目标。这只是一个事情是否可能的问题。
我不需要知道如何删除事件侦听器或管理事件侦听器,或删除文档的所有子元素。我想知道是否有可能销毁文档元素本身,不留下任何 <html>
标记并留下其事件侦听器的 none。 document.write()
可以做到这一点,但我只是想知道是否有其他方法可以实现这个确切的目标,而不是任何其他假定的目标。
您可以使用 document.getElementById('id-here').innerHTML = ""
,像这样:
<html id="the-website">
<body>
<input type="button" onclick="document.getElementById('the-website').innerHTML = '';" value="Don't click me plz!">
</body>
</html>
我不确定这个问题的背后是什么,但我猜,当页面中的对象和事件 re-created 时,您遇到了问题。
如果是这样的话,从MDN(https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild)中可以看出,尽管你删除了HTML上的元素,它们仍然可以在内存中保留一段时间,等待让垃圾收集器清理它们。
因此,如果您希望安全地删除一段包含事件的代码,最安全的方法是先使用您最喜欢的库(如 jQuery)或使用 DOM 删除事件通过本机 JavaScript: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
一旦你删除了所有事件,你就可以删除所有元素,最安全的方法(从内存的角度来看)是通过一个循环,先删除内部元素,然后删除父元素,等等。
我刚刚意识到实际上你可以,而且第一个示例 m1 实际上确实替换了 documentElement 并且 删除了它的事件侦听器。有趣的是,它首先没有事件侦听器,它们在 文档本身 而不是 文档元素 上。开发人员工具(在 FireFox 中)欺骗您并将它们显示为附加到 <html>
元素,即使它们在技术上并未附加到元素。如果您修改示例以实际将事件附加到 document.documentElement
而不是文档本身,则当您单击 m1:
document.documentElement.addEventListener('contextmenu', function (e) {
alert('still listening');
e.preventDefault();
})
function m1() {
var doc = document.implementation.createHTMLDocument();
document.replaceChild(
document.importNode(doc.documentElement, true),
document.documentElement
);
}
function m2() {
document.close();
document.write('<html></html>');
}
<button onclick="m1()">m1</button>
<button onclick="m2()">m2</button>
最初我打算说不,你不能这样做,正如用户 Livingston Samuel 在此 similar but not identical question 中所说:“你不能用 Document 替换当前文档对象或任何文档对象使用 createHTMLDocument 方法创建的对象。” 不过,坚持我原来的问题,这不是我要问的文档,而是 documentElement。所以鉴于上面修改后的代码,我会说是的,这是可能的。
有趣的是,从版本 81 开始,事件侦听器显示在 FireFox 的 html 元素上,无论它们是附加到文档对象还是 documentElement 对象。我可能希望它们会而不是在附加到 document
时根本不显示它们,或者将它们放在某个抽象对象上。 iframe 确实有一个可用的抽象对象,标签为 #document
,但它不用于此,也没有事件标签:
同样有趣的是,document.write()
实际上破坏了 document
对象上的事件,而不仅仅是 document.documentElement
。它可能在 here 的某处有记录,但我似乎找不到它。
测试后 Chrome 我注意到开发人员工具会区分附加到 documentElement 的事件:
和文档本身: