A deep dive into Backbone.View events
Backbone Views have a handy declarative events API. That lets you abstract your DOM event bindings into a declarative hash on your views prototype. For example
|
|
After your view is created and rendered, anytime a user clicks on the p
tag there will be a nice alert message in the console.
How does this work though? Let’s dive in and investigate.
Before we go into the exact details, let’s step through the path of setting up event handlers on DOM nodes to round out our perspective.
In the early days of html (V3.2) or so w3-spec
there was a call to allow users to harness a set of “intrinsic events that are generated by objects associated with HTML elements”, onClick
happens to be one of those. With that said, why don’t we turn back the clock and set up an “intrinsic” event?
|
|
Most people can agree nowadays that we want some degree of separation between our markup language and event bindings*, allowing a level of declarative control at a scripting level.
In comes the mythical JavaScript beast.
|
|
addEventListener
gives you the ability to register arbitrary event listeners on the event target, opening the door for dynamic event registration and essentially giving you the power to set up a reactive DOM tree depending on a user’s actions.
From there we waddle up the evolutionary tree into jQuery, and into the beauty of $.on
. At this point we can get back to the question initially proposed. How does the Backbone event hash really work?
Looking at the source for Backbone’s View class we see a call to delegateEvents
within our view constructor
Let’s step through this method line by line to really understand every single thing that it is doing.
|
|
After that look into how delegateEvents
works you may be thinking OK great now I know how it works. However I will challenge your understanding with a follow up. If you noticed that we call delegateEvents
in the view’s constructor, before we have ever called render.
So … We just registered a click handler on a p
tag that does not exist. addEventListener
would not work, so how does on
work before we have even rendered? Good question right?
Taking a look at the jquery docs reveals the answer to our puzzling question. In comes Direct and in our case delegated events.
Docs
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers
Meaning, since we know we have our root el
from Backbone that will eventually contain our template, we can use this feature of jQuery to take care of the deferred event registration for us.
In summary, the Backbone event hash does quite a bit more than simple registration of key value pairs. It abstracts a fairly complex set of concerns into a easy-to-decipher declarative API.
I hope you learned something, I know I did.
Thanks to Seebiscuit for asking this great question
in the Marionette Chatroom.
Sam Saccone
@samccone
[1] - Angular has ng-click
, and React has onClick
. There is a nice argument around coupling the event bindings to your template, but for this article that is not a battle I want to fight. :)
[2] - http://c2.com/cgi/wiki?GuardClause
[3] - http://api.jquery.com/on/#event-names http://api.jquery.com/event.namespace/