I am new to the spine and I try to understand all the zombie points of view.
Zombies, according to this article :
When we bind objects together through events, but we do not try to untie them. As long as these objects are connected to each other, and there is a link in our application code to at least one of them, they will not be cleaned or garbage collected. The resulting memory leaks are like movie zombies - hiding in dark corners, waiting to jump out and eat us for lunch.
The above article proposes to create an object that controls the transitions between views, and then implement the close function to remove and untie the view.
Moreover, depending on the situation, where to call this closure function from?
I add a property in the initialize block of my parent view to save the trace of the child view. That way, I can call .remove () on it before replacing it with a new one. Is this a good practice or is there a better way?
I also do not understand why the definition of el and then rendering with
this.$el.html(this.template(this.model.attributes));
doesn't allow me to cancel browsing while it is working as expected, doing
$('#sportsManDetails').html(this.$el.html(this.template(this.model.attributes)));
As for the example, I just created a simple application that displays a list of athlete names and shows more detailed information when you click on a name.
Here's the code and the working fiddle :
HTML
<script id="nameListTemplate" type="text/template"> <%= first %> <%= last %> </script> <script id="sportsManDetailsTemplate" type="text/template"> <ul> <li><%= first %></li> <li><%= last %></li> <li><%= age %></li> <li><%= sport %></li> <li><%= category %></li> </ul> <button class="test">Test</button> </script> <div id="sportsMenName"></div> <div id="sportsManDetails"></div>
Js
model and collection
var app = app || {}; app.SportsManModel = Backbone.Model.extend({}); app.SportsMenCollection = Backbone.Collection.extend({ model: app.SportsManModel });
Nameview
app.NameView = Backbone.View.extend({ tagName: 'li', className: 'sportsMan', template: _.template($('#nameListTemplate').html()), initialize: function(){ this.sportsManDetailsView; }, events: { 'click': 'showSportsManDetails' }, showSportsManDetails: function(e){ if (typeof this.sportsManDetailsView !== 'undefined'){ this.sportsManDetailsView.remove(); } this.sportsManDetailsView = new app.SportsManDetailsView({ model: this.model }) }, render: function(){ this.$el.append(this.template(this.model.attributes)); return this; } });
NameListView
app.NameListView = Backbone.View.extend({ el: '#sportsMenName', initialize: function(sportsMen){ this.collection = new app.SportsMenCollection(sportsMen); this.render(); }, render: function(){ this.collection.each(function(sportsMen){ this.renderContact(sportsMen); }, this); }, renderContact: function(sportsMen){ var nameView = new app.NameView({ model: sportsMen }); this.$el.append(nameView.render().el); } });
SportsManDetailsView
app.SportsManDetailsView = Backbone.View.extend({ // doesn't work if I use el in conjunction with // this.$el.html(this.template(this.model.attributes)); // el: '#sportsManDetails', template: _.template($('#sportsManDetailsTemplate').html()), initialize: function(){ this.render(); }, events: { 'click .test': 'test' }, test: function(){ alert('test'); }, render: function(){ // that does not work //this.$el.html(this.template(this.model.attributes)); // is this good practice? $('#sportsManDetails').html(this.$el.html(this.template(this.model.attributes))); } });
app.js
var sportsMen = [ {first: 'Quentin', last: 'Tarant', age: '34', sport: 'bike', category: '- 90kg'}, {first: 'Aymeric', last: 'McArthur', age: '54', sport: 'jetski', category: '200HP'}, {first: 'Peter', last: 'TheFat', age: '45', sport: 'curling', category: 'dunno'}, {first: 'Charles', last: 'Martel', age: '21', sport: 'Moto', category: 'MX 250cc'}, ]; $(function(){ new app.NameListView(sportsMen); });