Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone.js Events binding. Like "delegate" in Jquery?

I'm new in backbone.js. And I see that in Backbone.js, the events binding :

var PersonView = Backbone.View.extend({
    ....
    events : {
        "click button.btnSay" : "saySomething"
    },

    saySomething : function(){
        ....
    }
    ...
});

...doesn't need the button.btnSay to be existed in the time of calling, that's so similar to "delegate" in Jquery.

And now, the problem is, we can change any button in our html page to .btnSay (by Firebug, etc.). And they eventualy get the listeners. How can we prevent this?

like image 776
phnah Avatar asked Oct 18 '11 03:10

phnah


2 Answers

Under the hood, Backbone uses jQuery's "delegate" to wire up the events. So it's not that this is "like" jQuery, it is jQuery doing it for us.

To prevent scoping problems and ensure that our View events are only working with the HTML/DOM elements that we want, all events declarations are scoped to the View's el.

When a Backbone view is instantiated, an el attribute is either generated for you, or assigned by you. This gives you the opportunity to either attach your view to an existing chunk of the DOM or to create a new chunk of HTML that can be attached to the DOM.

Here's how you can attach to the existing DOM:

MyView = Backbone.View.extend({
  // ...
});

var existingDomEl = $("#someElement"); new MyView({ el: existingDomEl });

By specifying the el when we instantiate the view, or by specifying it directly in our view definition, we use an existing element.

If we omit the el from the constructor options and from the view definition, Backbone will generate an el for us. By default it will generate a div in el when the view is instantiated.

Once a View has it's el, whether through generation or assignment, the view's event declarations are delegated via jQuery, scoped to the view's el.

let's say you have the following html:

<div id="foo">
  <button class="btnSay">Say!</button>
</div>
<div id="bare">
  <button class="btnSay">Say, Part 2!</button>
</div>

with your example View, we could assign a view to either the foo or the bar element, and only the button within that element would get the click event.


var PersonView = Backbone.View.extend({
    ....
    events : {
        "click button.btnSay" : "saySomething"
    },

    saySomething : function(){
        ....
    }
    ...
});

new PersonView({
  el: $("#foo")
});

Now when you click the button in the foo div, you'll get the saySomething callback fired. But because the events for PersonView were scoped within the el for that instance of PersonView, clicking the button within bar will never fire the callback.

like image 162
Derick Bailey Avatar answered Dec 10 '22 09:12

Derick Bailey


It isn't similar to delegate it does use delegate (unless the event doesn't have a selector). The event binding in Backbone looks like this:

if (selector === '') {
  $(this.el).bind(eventName, method);
} else {
  $(this.el).delegate(selector, eventName, method);
}

So it uses delegate on the view's element. That at least limits the events to elements within the view.

You can't stop people from messing around with your elements and events in a debugger. They can change the HTML, the CSS, and even edit your JavaScript so you can't stop them from causing trouble on your page. You can stop them from making a mess on your server though, just don't trust anything that Backbone sends to your server and validate everything the same way you would validate anything else that comes in from the outside world.

Basically, don't waste your time worrying about someone smashing their own face with a brick by messing with your HTML/events/JavaScript. Let them hurt themselves all they want. But do protect your server by not trusting anything from the outside world (and your servers shouldn't even trust themselves any more than they have to).

like image 32
mu is too short Avatar answered Dec 10 '22 08:12

mu is too short