1

I am designing a new single page application with JavaScript and JQuery. However, my biggest concern is binding events ( like click, etc. ) via selectors to DOM elements that will be removed once a new "view" is loaded ( a new page is created from an AJAX call )

What is the cleanest way to implement a SPA without creating memory leaks and slowing the page down by replacing the main view DIV with new content?

kidalex
  • 1,437
  • 2
  • 12
  • 14
  • 1
    As long as you consistently use jQuery, you shouldn't have a problem. Meaning, if you want to remove a section and replace it, make sure you use jQuery methods (like `.remove()` or `.replaceWith()`), as they clean up what jQuery stores about them. People get into trouble when they decide to add event handlers with jQuery, then remove the elements with `.innerHTML = "whatever";` or use stuff like `parentElement.removeChild(el);` because it doesn't give jQuery a chance to clean up – Ian Jun 25 '13 at 18:38
  • You probably will want to use delegated events: http://api.jquery.com/on/ – cfs Jun 25 '13 at 18:40
  • Agree with both: using "on" and using "remove". But somehow I feel there is more to it. I mean people create entire frameworks for SPA! Or is it all fuss? – kidalex Jun 25 '13 at 21:13

1 Answers1

1

I know this is an old question but I thought it deserved an answer so here you go:

There are a couple of ways to go about this (it's a bit of a broad question so here is a bit of a broad answer):

FIRST WAY:

// This is in plain JS, but the jQuery equivalent is:
// document.on('click', '#my-id, function(e) { /* Function stuff */ });
document.addEventListener('click' function(e) {
  if (e.target.id === 'my-id') {
    // Function stuff
  }
});

The benefit of doing it this way is that you never have to remove an event listener, as there will always be a document. You could even set up a system of "stages" (I call them stages, I don't know if there is a better word for them) by using classes, i.e. your navigation links all have the class nav-item and in your event listener you could have this code:

// jQuery equivalent of if statement is: if ($(this).is('nav-item')) {}
if (e.target.className.match(/nav-item/)) { // You could also use .include(), etc.
  switch(e.target.id) {
    case 'item1':
      loadPageOneFunction(); // Or whatever
      break;
    case 'item2':
      loadPageTwoFunction(); // Or whatever
      break;
  }
}

SECOND WAY

// Note how I named the function
document.getElementById('my-id').addEventListener('click', function clickFunction(e) {
  myAjaxFunction(e.target); // Or whatever
});
// Later...
if (pageToLoad === 'page2') {
  // You are required to name the function you are removing.
  document.getElementById('my-id').removeEventListener('click', clickFunction);
  document.getElementById('my-page2-id').addEventListener('click', clickFunction);
}

I honestly prefer the first way as it is less code, I can use nameless functions (anonymous functions) - I know, big deal, but still...


There is a third way, which is just to not worry about removing the event listeners. You can read about that here.

Again, this is a very broad answer as its a broad question.

Community
  • 1
  • 1
4lackof
  • 1,250
  • 14
  • 33