Backbone.js events in my views being triggering mu

2019-02-17 19:17发布

问题:

I may have a misunderstanding on how to implement backbone.js, because all of my views that support multiple models (for example, a "Product" view that that can display multiple products), will send events to every view that was created in that session.

So in the example below, when I click the #redirect_product link, the "redirect_product" is called multiple times depending on how many products i've seen. If I've viewed 5 products, on the 6th click I will get 6 alerts.

What's going on here?

  505     /****************PRODUCT VIEW****************/
  506     App.Views.Product = Backbone.View.extend({
  507         el: $('#content_sec'),
  508 
  509         events: {
  510             "click #redirect_product": "redirect_product",
  511         },
  512 
  513         initialize: function(options) {
  514             this.model = this.options.model;
  515             this.render();
  516 
  517         },
  518 
  519         render: function() {
  520             $(this.el).empty();
  521             $('#product_detail_template').tmpl(this.model.toJSON()).appendTo($(this.el));
  522 
  523 
  524             //Activate facebook buttons
  525             if (typeof FB  != "undefined"){
  526                         FB.XFBML.parse(document.getElementById('item_share'))
  527             }
  528 
  529             wishlist.init();
  530             return this;
  531         },
  532 
  533         redirect_product: function() {
  534             //Send data on what product being clicked by whom
  535             alert('hi');
  536 
  537 
  538             //Open new window with product for user
  539             var external_link = this.model.get('product').attributes['External Link'];
  540             window.open(external_link, "external_site");
  541 
  542         },
  543     });

回答1:

The problem, I think, is that your using the same el for all your views.

When you create a new Product, do something like this:

$('#content_sec').append('<div class="productView"></div>');
var product = new Product();
var view = new ProductView({model: product, el: $('.productView:last')});

Once each product has its own scope, then the events will work as expected.



回答2:

From my practice, the best way to handle views with multiple models is to have two kinds of views:

  • parent view (with Collection as a model) - think of it as <ul>
  • child views (with Models from the collection) - think of it as <li>

Your parent view renders all the child views and observes Collection changes.

Each of the child views limits its scope to the li element, so each event on a model (its view) is handled separately.

It's easier to maintain, cleaner and gives a better overview on the model-view relationship.



回答3:

Replace id "#redirect_product" with a class ".redirect_product" Then you can have many of them on the page.

Most of the time in backbone views I only use classes. Very rarely id's. Given that backbone has a finder

this.$(".redirect_product")

that only searches in scope of the view you don't need to care too much if the class is also existing on another element outside the scope of the view.