These lines in the bootstrap affix plugin seem to cause a memory leak because the window gets a reference to the affix instance that's never released.
As a workaround I'm using this code to release the references when removing the affixed element from the DOM:
$(window)
.off('scroll.bs.affix.data-api')
.off('click.bs.affix.data-api');
Seems kind of hacky- is there a better way of doing this? Didn't see anything in the affix plugin docs.
These lines in the bootstrap affix plugin seem to cause a memory leak because the window gets a reference to the affix instance that's never released.
As a workaround I'm using this code to release the references when removing the affixed element from the DOM:
$(window)
.off('scroll.bs.affix.data-api')
.off('click.bs.affix.data-api');
Seems kind of hacky- is there a better way of doing this? Didn't see anything in the affix plugin docs.
Share Improve this question edited Feb 27, 2018 at 10:33 Mosh Feu 29.4k18 gold badges93 silver badges141 bronze badges asked Feb 11, 2014 at 21:32 Jeremy DanyowJeremy Danyow 26.4k12 gold badges90 silver badges135 bronze badges 2- Additionally can I ask why you're removing built in references that are included in BS3 by default? – Raptus Commented Jul 3, 2014 at 10:22
- I am not fully understand why there is a leak. If possible, can you elaborate it a bit more? An example would be good. Thanks! – Nicolas S.Xu Commented Aug 29, 2014 at 8:56
3 Answers
Reset to default 1By default, bootstrap Affix listens for scroll
and click
events on $(window)
using the .bs
, .affix
, and .data-api
namespaces.
$.off('.affix');
will remove all listeners in the .affix
namespace.
$(window).off('.affix');
will remove all listeners in the .affix
namespace from the window element. If you only have one Affix, and are affixing it to the window, it has the exact same effect as $.off('.affix');
Adding in the other namespaces makes it more specific, but unless you are using the .affix
namespace in your own code, the added specificity doesn't change anything. You don't want to remove the other namespaces independently of .affix
if you are using any other bootstrap elements.
$('.affix').off('.affix');
will not work because the listeners are not on the Affixed element, but on the target that element is Affixed to, i.e. the window.
pstenstrm is correct that there is no way to detect that an element is removed from the DOM, or injected for that matter. So if the code later re-injects the element, and you want to behave as an Affix again, you'll need to use the bootstrap JS api to call Affix again.
I took @Carrie Kendall's remendation and opened a bug report... well mented on a related bug report.
https://github./twbs/bootstrap/issues/13655
What we need in this case is a "destroy" method for the affix plugin and some documentation on the getbootstrap site so that people using the affix plugin in single page apps can avoid the memory leak pitfall when removing their affixed content.
There is no way to detect when an element is removed from the DOM. The affix plugin can't automatically remove the listeners. The way you do it is the right way.
Though by calling $(window).off()
you remove every listener, even those you might want to keep. It would be safer to only call $.off()
on the element you are removing.
$('.affix').off('.affix');
The .bs
, .affix
and .data-api
after the event name are namespaces. By calling $.off('.affix')
you remove every event declared in that namespace. Which is probably the only better of doing what you're doing.