J'apprends le développement d'applications JavaScript MVC à l'aide de Backbone.js et j'éprouve des difficultés à rendre la collection de modèles dans la vue. Voici ce que je veux faire:
Une fois le chargement de la page terminé, récupère les données du serveur en tant que collection de modèles.
Rendez-les dans la vue
C'est tout ce que je veux faire et voici ce que j'ai jusqu'à présent:
$(function(){
"use strict";
var PostModel = Backbone.Model.extend({});
var PostCollection = Backbone.Collection.extend({
model: PostModel,
url: 'post_action.php'
});
var PostView = Backbone.View.extend({
el: "#posts-editor",
initialize: function(){
this.template = _.template($("#ptpl").html());
this.collection.fetch({data:{fetch:true, type:"post", page:1}});
this.collection.bind('reset', this.render, this);
},
render: function(){
var renderedContent = this.collection.toJSON();
console.log(renderedContent);
$(this.el).html(renderedContent);
return this;
}
});
var postList = new PostCollection();
postList.reset();
var postView = new PostView({
collection: postList
});
});
Pour autant que je sache, Chrome enregistre la réponse du serveur et elle est au format JSON comme je le veux. Mais cela ne rend pas à mon avis. Il n'y a pas d'erreur apparente dans la console.
Le serveur a un gestionnaire qui accepte les paramètres GET et echo certains JSON: http://localhost/blog/post_action.php?fetch=true&type=post&page=1
[
{
"username":"admin",
"id":"2",
"title":"Second",
"commentable":"0",
"body":"This is the second post."
},
{
"username":"admin",
"id":"1",
"title":"Welcome!",
"commentable":"1",
"body":"Hello there! welcome to my blog."
}
]
Il y a 2 problèmes potentiels avec votre code.
Le rappel de l'écouteur d'événements doit être enregistré before en appelant la collection.fetch()
. Sinon, vous risquez de manquer le premier événement reset
car il pourrait être déclenché avant que l'écouteur ne soit enregistré.
L'événement reset
n'est pas suffisant pour garantir que la vue sera rendue à chaque nouvelle mise à jour de la collection.
Notez également qu'il est recommandé d'utiliser le formulaire object.listenTo()
pour lier des événements, car cela garantira la suppression de l'enregistrement lorsque la vue est fermée. Sinon, vous risquez de vous retrouver avec ce que l’on appelle les zombies de la colonne vertébrale . Voici une solution.
this.listenTo( this.collection, 'reset add change remove', this.render, this );
this.collection.fetch({ data: { fetch:true, type:"post", page:1 } });
Notez comment vous pouvez enregistrer plusieurs événements à partir du même objet en les séparant par des espaces.
changement
this.collection.bind('reset', this.render, this);
à
this.collection.bind('sync', this.render, this);
Le problème est que vous effectuez une réinitialisation une seule fois, au début. Et à ce moment-là, vous n'avez rien à rendre. La prochaine fois que vous récupérerez votre collection, l'événement reset ne se déclenchera pas, car vous extrayerez une collection sans l'option {reset: true}.
Changer cette ligne
this.collection.bind('reset', this.render, this);
à
this.listenTo(this.collection, 'reset', this.render);
Lors de l'extraction de votre collection, l'événement de réinitialisation n'est plus déclenché par défaut. (Je crois depuis la version 1.0) Pour que Backbone déclenche l'événement reset lorsque la collection a été extraite, vous devez maintenant appeler la méthode fetch de la manière suivante:
this.collection.fetch({reset: true});