如果删除元素,我是否必须清除 DOM 中的事件?

发布于 2024-12-07 11:32:28 字数 479 浏览 0 评论 0 原文

假设我有一个动态加载页面的页面。当每个页面加载到 DOM 中时,就会添加该页面中元素的事件。

如果用户加载另一个页面,先前加载的元素将从 DOM 中删除。当然,由于元素本身不再存在,映射到这些元素的任何事件都将停止运行。

然而,它们也被删除了吗?或者它们是否存在于用户的记忆中,占用空间?

后续: 是否有这样定义的函数:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

可以使用 event = null 轻松删除事件(或者我是这么假设的!)...

但是如果事件没有保存到局部变量中怎么办?

$('foobar').addEvent('click', function() {
    alert(1);
});

谢谢!

Let's say I have a page that loads pages dynamically. As each page loads into the DOM, events for the elements in that page are added.

If the user loads another page, the elements loaded previously will be removed from the DOM. Naturally, because the elements themselves no longer exist, any events mapped to those elements cease to function.

However, are they also removed? Or are they sitting in the user's memory, taking up space?

Follow-up:
Were a function defined as such:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

One could easily remove the event with event = null (or so I'd assume!)...

but what if the event were not saved to a local variable?

$('foobar').addEvent('click', function() {
    alert(1);
});

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不喜欢何必死缠烂打 2024-12-14 11:32:28

首先。什么?这是没有意义的:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

它不会像您想象的那样将事件保存到局部变量中。它将对 foobar 元素对象 的引用保存到 event 变量中 - 大多数 mootools 元素方法将返回 this 进行链接,即元素本身而不是方法的结果(除非它是像“.getStyle”这样的吸气剂)。

这取决于你如何摆脱这个元素,接下来会发生什么。首先,element.destroy,在这里找到:https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L728

它将从 dom 和内存中删除元素,并以安全的方式清空它。一旦它消失,它将依赖于浏览器的 GC 进行清理,mootools 不会为元素本身执行任何壮观的 GC,但它也会在子节点上运行特殊的 clean 函数:varchildren = clean(this).getElementsByTagName('*');

clean 方法还会删除附加到 div 子元素的任何事件处理程序和存储。

然后。 mootools 添加的事件进入元素存储。元素存储位于元素原型使用的闭包后面的对象中。为了测试它,我们将重新实现它并使其可刺穿(称为存储的全局对象),以便我们可以检查父级消失后引用会发生什么:

http://jsfiddle.net/dimitar/DQ8JU/

(function() {
    var storage = this.storage = {}; // make it puncturable

    var get = function(uid){
        return (storage[uid] || (storage[uid] = {}));
    };

    Element.implement({
       retrieve: function(property, dflt){
            var storage = get($uid(this)), prop = storage[property];
            if (dflt != null && prop == null) prop = storage[property] = dflt;
            return prop != null ? prop : null;
        },

        store: function(property, value){
            var storage = get($uid(this));
            storage[property] = value;
            return this;
        },

        eliminate: function(property){
            var storage = get($uid(this));
            delete storage[property];
            return this;
        }


    });

})();

// read it.
var link = document.getElement("a");
var uid = link.uid; // will reference the mootools unique id for it

// add an event handler
link.addEvent("click", function(e) {
    console.log("hi");
    this.destroy();
    // see what's left in storage for that element.
    console.log(storage[uid]);

    // storage should be empty.
    console.log(storage);
});

link.getFirst().addEvent("mouseenter", function() {
   console.log("over");
});

// check to see if it is there via element storage API.
console.log(link.retrieve("events").click);

// check to see if it's there via our puncture
console.log(this.storage[uid]);

// see all events in storage, inc child element:
console.info(this.storage);

这一切证明的是,mootools 可以清理所有你需要清理的东西。只要您不在使用的元素上使用任何内联 onclick= 内容,就可以了。在 mootools 的垃圾收集和浏览器之间,您可以得到很好的保护。请注意,如果回调是匿名的,您可以在单个元素上堆叠多个事件。

first of all. what? this makes no sense:

var event = $('foobar').addEvent('click', function() {
    alert(1);
});

it does not save the event into a local variable as you seem to think. it saves a reference to the foobar element object into the event variable - most mootools element methods will return this for chaining, which is the element itself and not the result of the method (unless it's a getter like '.getStyle').

it then depends on how you get rid of the element what happens next. first off, element.destroy, found here: https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L728

it will remove the element from the dom and from memory, and empty it in a safe way. it will be reliant on the browser's GC to clean up once it's gone, mootools won't do any spectacular GC for you for the element itself but it does run the special clean function on the child nodes as well: var children = clean(this).getElementsByTagName('*');.

the clean method also gets rid of any event handlers and storage attached to the child elements of the div.

THEN. events added by mootools go into element storage. Element storage is in an object behind a closure which the element proto uses. To test it, we will re-implement it and make it puncturable (a global object called storage) so we can check what happens to the reference after the parent is gone:

http://jsfiddle.net/dimitar/DQ8JU/

(function() {
    var storage = this.storage = {}; // make it puncturable

    var get = function(uid){
        return (storage[uid] || (storage[uid] = {}));
    };

    Element.implement({
       retrieve: function(property, dflt){
            var storage = get($uid(this)), prop = storage[property];
            if (dflt != null && prop == null) prop = storage[property] = dflt;
            return prop != null ? prop : null;
        },

        store: function(property, value){
            var storage = get($uid(this));
            storage[property] = value;
            return this;
        },

        eliminate: function(property){
            var storage = get($uid(this));
            delete storage[property];
            return this;
        }


    });

})();

// read it.
var link = document.getElement("a");
var uid = link.uid; // will reference the mootools unique id for it

// add an event handler
link.addEvent("click", function(e) {
    console.log("hi");
    this.destroy();
    // see what's left in storage for that element.
    console.log(storage[uid]);

    // storage should be empty.
    console.log(storage);
});

link.getFirst().addEvent("mouseenter", function() {
   console.log("over");
});

// check to see if it is there via element storage API.
console.log(link.retrieve("events").click);

// check to see if it's there via our puncture
console.log(this.storage[uid]);

// see all events in storage, inc child element:
console.info(this.storage);

what all this proves is, mootools cleans up all you need cleaned. as long as you don't use any inline onclick= stuff on elements you work with, you're going to be fine. Between mootools' garbage collection and the browser, you are well covered. just be aware you can stack up multiple events on a single element if the callbacks are anonymous.

行至春深 2024-12-14 11:32:28

有趣的问题...阅读以下内容:https://developer.mozilla。 org/en/DOM/element.addEventListener#Memory_issues

要使用 jQuery 删除事件侦听器,请参阅 http://api.jquery.com/unbind/

Interesting question... have a read of this: https://developer.mozilla.org/en/DOM/element.addEventListener#Memory_issues

To remove the event listener using jQuery, see http://api.jquery.com/unbind/

当梦初醒 2024-12-14 11:32:28

我发现旧版本的 IE 似乎在添加和删除大量绑定事件的元素时存在问题。主要原因是循环引用无法被垃圾收集。您可以在此处找到更多信息:http://msdn.microsoft.com/en-us/ library/Bb250448

设置为 null 不会删除该事件,它只会删除对该事件的引用。您需要同时使用 element.removeEventListener 和 element.detachEvent (取决于浏览器),或者如果您使用 jquery unbind 应该可以工作。

此外,还有一些工具可用于检测泄漏,这个工具效果很好(根据同事的说法):http://blogs.msdn.com/b/gpde/archive/2009/08/03/javascript-memory-leak- detector-v2.aspx

I have found that older versions of IE seems to have issues with adding and removing lots of elements with events binded to them. The main cause is circular references that cannot be garbage collected. You can find more information here: http://msdn.microsoft.com/en-us/library/Bb250448

Setting to null will not remove the event, it would just remove the reference to the event. You need to use both element.removeEventListener and element.detachEvent (depending on browser), or if you are using jquery unbind should work.

Also, there are tools available to detect leaks, this one works well (according to coworker): http://blogs.msdn.com/b/gpde/archive/2009/08/03/javascript-memory-leak-detector-v2.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文