Binding events to views - Firing uneven number of times

后端 未结 2 661
挽巷
挽巷 2021-01-29 06:47

I have UserModel: UserView and UserCollection: UserCollectionView. With this, I am trying to bind a click event

相关标签:
2条回答
  • 2021-01-29 07:15

    The main problem is that you are rendering all UserView views in the same container:

     $('#users-list').append(this.template(this.model.toJSON()));
    

    This is why the click event selector('click .user-data') is selecting the other UserView buttons and firing it's clicks too.

    You didn't ask but... here it goes some suggestions:

    1. Do not call render from the initialize function;
    2. Avoid defining the el;
    3. Avoid adding the view content outside the view using $. Use this.$el instead;
    4. NEVER forget to return this; at you render functions.

    Here is a jsfiddle with what I think you want: https://jsfiddle.net/Neviton/n52j873u/

    0 讨论(0)
  • 2021-01-29 07:16

    There are many issues with your code.

    Main problem is that, all your userView's are pointing to the same selector, and the element matching this selector .user-box-wrapper is inside the view template - So whenever you create a new userView, it'll add a new event listener to .user-box-wrapper present in all existing userViews, but not to itself. So your first userView will have n-1 events handlers registered to it while last one has none (n being total number of userViews). View element is not supposed to be part of template, template is supposed to be added to the view element.

    When your view will have multiple copies of itself, don't define el option, let backbone create a new element for each instance of the view. You can customize the properties of this element.

    Another issue is that you are not appending the userView template to your userView element, but something else outside it ($('#users-list'). So clicking the template won't trigger the event handler (in your case this is why you're last userView doesn't fire it's event. It was bound to all other existing views because common selector was provided by el)

    You should try to avoid global selectors like $('#users-list') from within a view. In this case you can append the userView to #users-list from within userCollectionView who's el points to #users-list.

    Your code should be:

    var root = 'http://localhost:5000/api/v1';
    var app = {};
    
    // Backbone Model
    app.UserModel = Backbone.Model.extend({
      defaults: {
        // urlRoot: root + '/users',
        name: 'Default Name',
        email: '30',
        username: 'default_username'
      },
    
      initialize: function() {
        this.set({
          id: this.get('username')
        });
        console.log('User model \'' + this.id + '\' has been initialized.');
      }
    });
    
    // Backbone Model View
    app.UserView = Backbone.View.extend({
      className: 'user-box-wrapper',
      /*--^-- creates a new div with this class for each user*/
      template: _.template($('#connections-user-template').html()),
      events: {
        'click .user-data': 'userClicked'
      },
      initialize: function() {
        this.render();
      },
      render: function() {
        this.$el.append( this.template( this.model.toJSON()));
        console.log('User view is rendered');
      },
      userClicked: function(ev) {
        console.log("User selected");
        // console.log(ev.currentTarget);
      }
    });
    
    // Backbone Collection
    app.UserCollection = Backbone.Collection.extend({
      model: app.UserModel,
      url: root + '/users',
      initialize: function() {
        // this.fetch();
      },
      parse: function(data) {
        // console.log(data.data);
        return data.data;
      }
    });
    
    // Backbone Collection View
    app.UserCollectionView = Backbone.View.extend({
      el: '#users-list',
      template: _.template($('#connections-template').html()),
      initialize: function() {
        this.connections = new app.UserCollection();
        var self = this;
        this.connections.fetch().done(function() {
          self.render();
        });
      },
      render: function() {
        this.$el.html(this.template());
        console.log('User collection view is rendered');
        this.connections.each(function(user) {
          console.log('User : ' + user.get('id'));
          var userView = new app.UserView({
            model: user
          });
          this.$el.append(userView.el); /*append child view here*/
        },this);
      }
    });
    var connectionsView = new app.UserCollectionView();
    
    0 讨论(0)
提交回复
热议问题