Backbone.js | Comment puis-je stocker des éléments d'une vue pour plus tard la récupération?
-
13-10-2019 - |
Question
Ceci est ma première tentative d'utiliser Backbone.js, alors j'ai décidé de faire une application de test simple qui simule un menu de restaurant avec des éléments de menu. Je suivais avec ce refroidir blog de andyet.net .
Je vais avoir un problème lors de l'ajout d'un modèle à une collection. Je suis lié une méthode en vue de l'événement ajouter de la collection qui devrait mettre à jour la vue. Voici le code le plus de code non pertinent supprimé possible.
(note: je retire des choses comme des déclarations SCOPE var
locales et des fermetures pour des raisons de concision qui suit est encore un peu de temps, et je sais que c'est ennuyeux, mais il devrait être assez simple et facile à comprendre.) :
MenuItem = Backbone.Model.extend({
// initialize functions removed for brevity
});
Menu = Backbone.Model.extend({
// initialize functions removed for brevity
// MenuSelection property is defined here.
});
MenuSelection = Backbone.Collection.extend({ model: MenuItem });
MenuItemView = Backbone.View.extend({
// render template
});
/**
* This is unaltered from the code. The error occurs here.
*/
RestaurantAppView = Backbone.View.extend({
addMenuItem : function (MenuItem) {
var view = new MenuItemView({ model : MenuItem });
this.menuList.append(view.render().el);
// ERROR occurs here. error: "this.menuList is undefined"
},
initialize : function () {
this.model.MenuSelection.bind('add', this.addMenuItem);
},
render : function () {
$(this.el).html(ich.app(this.model.toJSON()));
this.menuList = this.$('#menuList'); // IT IS DEFINED HERE
return this;
}
});
/**
* Everything after this I left in just-in-case you need to see it.
*/
RestaurantAppController = {
init : function (spec) {
this.config = { connect : true };
_.extend(this.config, spec);
this.model = new Menu({
name : this.config.name,
});
this.view = new RestaurantAppView({ model : this.model });
return this;
}
};
$(function() {
// simulating ajax JSON response.
var json = {
Menu : {
name : 'Appetizers',
MenuItem : [
{
name : 'toast',
description : 'very taosty',
price : '$20.00'
},
{
name : 'jam',
description : 'very jammy',
price : '$10.00'
},
{
name : 'butter',
description : 'very buttery',
price : '$26.00'
}
]
}
};
window.app = RestaurantAppController.init({
name : json.Menu.name
});
$('body').append(app.view.render().el);
app.model.MenuSelection.add(json.Menu.MenuItem);
});
J'ai marqué des commentaires de la zone problématique. Selon le Documentation Backbone :
Si jQuery ou Zepto est inclus sur la page, chaque vue a une fonction de $ que les requêtes runs scope au sein de l'élément de la vue.
Donc, si je suis la mise en this.menuList = this.$('#menuList');
dans la méthode render, pourquoi puis-je pas accès this.menuList
dans la méthode addMenuItem
? La I démonstration liée au haut-t-il exacly comme ça. De plus, si j'échange sur this.menuList
pour un sélecteur jQuery, comme suit:
addMenuItem : function (MenuItem) {
var view = new MenuItemView({ model : MenuItem });
$('#menuList').append(view.render().el);
}
Tout fonctionne très bien. Mais je ne sais pas veulent sélectionner à nouveau l'ID menulist chaque addMenuItem
temps est exécuté. Le RightWay TM est-à cache après qu'il est rendu.
A noter également:. Je pensais que le problème était avec le modèle ICanHaz ne revient pas assez vite, mais this.menuList
serait un tableau vide, pas undefined
, de sorte que ce pas
La solution
Vous êtes en cours d'exécution dans le # 1 Gotcha avec JavaScript - le mot-clé this
scope dynamiquement. Lorsque vous tirez hors this.addMenuItem
comme référence sans le liant, la fonction addMenuItem
perd sa notion de this
. Il y a deux façons simples de le fixer dans votre code, remplacez cette ligne:
this.model.MenuSelection.bind('add', this.addMenuItem);
Avec ceci:
this.model.MenuSelection.bind('add', _.bind(this.addMenuItem, this));
Ou ajoutez cette ligne en haut de votre fonction initialize, ce qui permettra d'accomplir efficacement la même chose:
_.bindAll(this, 'addMenuItem');
Autres conseils
Probablement la méthode addMenuItem est appelée avant de rendre la méthode est appelée et donc la définition de MenuList manque dans le addMenuItem.
Pourquoi ne pas vous pousser this.menuList = $ this- ( '# MenuList'). initialize méthode et essayer