MyMapStaticObject
var PlaceViewModel = function(){
MyMapStaticObject.addLayer(someLayer);
}
PlaceViewModel.prototype.addMarker = function(item){
}
我有一个 PlaceViewModel ,它有一个名为addMarker
的函数,可以将标记添加到地图中。我将在不同的类中使用 PlaceViewModel new istances。
var inst = new PlaceViewModel();
初始化PlaceViewModel时,我正在通过 MyMapStaticObject 添加新图层。我应该在实例销毁时删除图层。
我可以处理javascript destroy事件吗?
答案 0 :(得分:3)
Javascript没有销毁事件。它是一种垃圾收集语言,当不再有任何代码可以访问对象引用时,它将释放一个对象。当它释放对象时,它不会提供任何事件来通知它。
如果你想实现一些将删除图层的清理代码,那么你必须添加一个你可以在完成对象时调用的方法,这样你就可以调用该方法,它可以然后删除该方法中的图层。调用此方法必须是您手动操作(很可能它将被挂钩到代码中正在进行的其他操作的管理中,您可以在适当的时间通过该代码调用它。)
答案 1 :(得分:1)
在这里参加聚会有点晚,但是我想知道什么时候物体被销毁了。问题是JS没有任何内置方法来执行此操作。我想要这样做,以便可以将websocket事件添加到页面,然后在页面转到另一个页面时将其删除,当然我可以在页面加载部分中实现此功能,但是我有不同的框架,并且希望有一个更通用的解决方案对象破坏问题。 Javascript是一种垃圾收集语言,但是如果我们也可以附加一些生命周期事件,那还是很不错的。当然有代理服务器,但再次对这里无济于事,因为我需要知道代理服务器本身已被删除。
好吧,您确实有一个地方会发生销毁事件,而MutationObserver就是其中之一,大多数现代浏览器现在都支持该事件。它不是严格销毁,而是从DOM中添加和删除节点。但是总的来说,如果您有事件,您可能还会有一个可以附加的DOM节点,或者即使它不可见,也可以添加一个不可见的DOM元素。
因此,我有一个名为domDestroy(element, obj)
的小函数,当它检测到element
被删除时,它将检查obj
是否具有destroy
方法(如果存在)它会调用它。
现在我要了解的一个问题是,我是在一个隐藏的DOM节点中创建页面的,当然,当我将其放入可见的DOM节点时,由于要与不可见的DOM节点分离,然后再附加,我得到了删除。到可见的DOM。根本不是我们想要的。
解决方案非常简单,例如,当进行这种双重缓冲时,通常只需一步即可完成。隐藏当前页面,显示新页面。因此,我要做的是跟踪何时将其删除并保存在一个简单的Set中,然后还要跟踪添加的元素,如果该元素是Set中的一部分,我将删除它。然后,我只需要在下一个刻度上再次检查此Set,如果它仍然存在,它实际上已被删除,我们将调用该对象的destroy方法。
下面是一个简单的示例,基本上,如果右键单击并检查页面,则可以通过拖放来上下移动LI,这将导致DOM分离并重新连接。但是,如果您改为删除一个LI,您会注意到它说出delete then,因为它现在知道它没有重新连接到另一个DOM。
当然,需要注意的一件事是,如果您对DOM元素进行任何附加/分离,请尝试在同一时间间隔内执行此操作:IOW:请注意两者之间的异步操作。另外,您也可以使用分离的DOM来构建页面,在这里,您也可以轻松更改功能以解决此问题,基本上使用destroyObserver.observe(
添加这些功能。
const dsy = "__dom-destroy-obj";
const destroyList = new Set();
let tm;
function cleanUp() {
tm = null;
for (const el of destroyList) {
for (const d of el[dsy]) {
d.destroy();
}
}
destroyList.clear();
}
function checkDestroy(el) {
if (el[dsy]) {
for (const d of el[dsy]) {
if (!d.destroy) {
console.warn("No destroy, on dom-destroy-obj target");
} else {
destroyList.add(el);
if (tm) return; //already a timer running
tm = setTimeout(cleanUp, 1);
}
}
}
if (el.childNodes) for (const n of el.childNodes) checkDestroy(n);
}
function checkAdded(el) {
if (el[dsy]) {
destroyList.delete(el);
}
if (el.childNodes) for (const n of el.childNodes) checkAdded(n);
}
const destroyObserver = new MutationObserver(
function (mutations) {
for (const m of mutations) {
if (m.removedNodes.length) {
for (const i of m.removedNodes) {
checkDestroy(i);
}
}
if (m.addedNodes.length) {
for (const i of m.addedNodes) {
checkAdded(i);
}
}
}
}
);
destroyObserver.observe(document.body, {
childList: true,
subtree: true
});
function domDestroy(element, obj) {
if (!element[dsy]) element[dsy] = new Set();
element[dsy].add(obj);
}
//simple test.
for (const i of document.querySelectorAll("li")) {
domDestroy(i, {
destroy: () => console.log("destroy")
});
}
<span>
From your browsers inspector, try moving the LI's, and deleting them. Only when you delete the DOM node, should the destroy method get called.
</span>
<ul>
<li>Re order</li>
<li>Or delete</li>
<li>Some of these</li>
</ul>