Nous avons vu comment les propriétés observables permettent à Knockout.js de mettre à jour automatiquement les éléments HTML lorsque les données sous-jacentes changent, mais ce n'est que le début de leur utilitaire. Knockout.js propose également deux autres moyens d'exposer les propriétés de ViewModel: les observables calculés et les tableaux observables. Ensemble, ils ouvrent un tout nouveau monde de possibilités pour les interfaces utilisateur pilotées par les données..
Observables calculés vous permettent de créer des propriétés générées dynamiquement. Cela signifie que vous pouvez combiner plusieurs variables observables normales dans une même propriété et Knockout.js conservera toujours la vue à jour chaque fois que l'une des valeurs sous-jacentes change..
Figure 12: Observable calculé dépendant de deux observables normaux
Tableaux observables combinez la puissance des observables de Knockout.js avec des tableaux JavaScript natifs. Comme les tableaux natifs, ils contiennent des listes d'éléments que vous pouvez manipuler. Mais comme ils sont observables, Knockout.js met automatiquement à jour les éléments HTML associés chaque fois que des éléments sont ajoutés ou supprimés..
Figure 13: Un tableau observable contenant d'autres ViewModels
La possibilité de combiner des éléments observables, ainsi que la capacité de travailler avec des listes d’éléments, fournit toutes les structures de données dont vous avez besoin dans ViewModel. Cette leçon présente les deux sujets avec une interface de panier d'achat simple..
Observables calculés
Commençons par un simple observable calculé. Sous le Prénom et nom de famille observables dans PersonViewModel, créez l'observable calculé complet:
Ceci définit une fonction anonyme qui renvoie le nom complet de la personne chaque fois que PersonViewModel.fullName est accédé. Générer dynamiquement le nom complet à partir des composants existants (Prénom et lastName) nous empêche de stocker des données redondantes, mais ce n'est que la moitié de la bataille. Nous devons passer cette fonction à ko.computed () pour créer un observable calculé. Cela indique à Knockout.js qu'il doit mettre à jour tous les éléments HTML liés à la propriété fullName à chaque changement de firstName ou lastName..
Faisons en sorte que nos travaux observables calculés soient liés en associant la ligne «Panier de John» à nom complet au lieu de firstName:
Panier d'achat
Votre page devrait maintenant se lire "Panier de John Smith". Nous allons maintenant nous assurer que Knockout.js garde cet élément HTML synchronisé lorsque nous changeons l'une des propriétés sous-jacentes. Après avoir lié une instance de PersonViewModel, essayez de changer sa propriété firstName:
var vm = new PersonViewModel (); ko.applyBindings (vm); vm.firstName ("Mary");
Cela devrait changer la ligne en «Panier d'achat de Mary Smith». Encore une fois, rappelez-vous que la lecture ou le paramétrage d'observables doit être effectué avec des appels de fonction et non avec l'attribution (=) opérateur.
Les observables calculés offrent bon nombre des mêmes avantages que la synchronisation automatique de la vue par Knockout.js. Au lieu de devoir savoir quelles propriétés dépendent d'autres parties du ViewModel, les observables calculés vous permettent de construire votre application autour de propriétés atomiques et de déléguer le suivi des dépendances à Knockout.js..
Tableaux Observables
Les tableaux observables permettent à Knockout.js de suivre les listes d’éléments. Nous allons explorer cela en créant une page d'affichage de panier pour notre utilisateur. Tout d'abord, nous devons créer un objet personnalisé pour représenter les produits. En haut de notre script, avant de définir PersonViewModel, ajoutez la définition d'objet suivante:
fonction Produit (nom, prix) this.name = ko.observable (nom); this.price = ko.observable (prix);
Ceci est juste un objet de données simple pour stocker quelques propriétés. Notez qu'il est possible de donner à plusieurs objets des propriétés observables, et Knockout.js gérera lui-même toutes les interdépendances. En d'autres termes, il est possible de créer des relations entre plusieurs ViewModels dans une seule application.
Ensuite, nous allons créer quelques instances de notre nouvelle Produit classe et les ajouter au panier virtuel de l'utilisateur. À l'intérieur de PersonViewModel, définir une nouvelle propriété observable appelée shoppingCart:
this.shoppingCart = ko.observableArray ([nouveau produit ("bière", 10,99), nouveau produit ("brats", 7,99), nouveau produit ("petits pains", 1,49)]);
Il s'agit d'un tableau JavaScript natif contenant trois produits encapsulés dans un tableau observable afin que Knockout.js puisse suivre le moment où des éléments sont ajoutés et supprimés. Mais avant de commencer à manipuler les objets, mettons à jour notre vue pour pouvoir voir le contenu de la chariot propriété. Sous le
tag, ajoutez ce qui suit:
Produit
Prix
Il s'agit d'un tableau HTML 5 typique contenant une colonne pour les noms de produits et une autre pour les prix des produits. Cet exemple introduit également une nouvelle liaison appelée pour chaque. Quand Knockout.js se rencontre pour chaque: shoppingCart, il parcourt chaque élément du ViewModel chariot propriété. Tout balisage à l'intérieur de la boucle est évalué dans le contexte de chaque élément. Ainsi, text: name fait en réalité référence à shoppingCart [i] .name. Le résultat est un tableau des articles à côté de leurs prix:
Figure 14: Capture d'écran de la liste de produits rendue
Les détails de la pour chaque contraignantes sortent du cadre de cette leçon. La prochaine leçon propose une discussion approfondie de foreach et présente également les autres liaisons de flux de contrôle de Knockout.js. Pour l'instant, revenons aux tableaux observables.
Ajout d'éléments
L’intérêt des tableaux observables est de laisser Knockout.js synchroniser la vue chaque fois que nous ajoutons ou supprimons des éléments. Par exemple, nous pouvons définir une méthode sur notre ViewModel qui ajoute un nouvel élément, comme ceci:
this.addProduct = function () this.shoppingCart.push (nouveau produit ("Plus de bière", 10.99)); ;
Ensuite, nous pouvons créer un bouton pour appeler la méthode afin d’ajouter des éléments au moment de l’exécution et de voir Knockout.js tenir la liste à jour. À côté du bouton de paiement dans le code d'affichage, ajoutez les éléments suivants:
Lorsque vous cliquez sur ce bouton, le ViewModel addProduct () La méthode est exécutée. Et depuis chariot est un tableau observable, Knockout.js en insère un autre
élément pour afficher le nouvel élément. Laisser Knockout.js garder la trace des éléments de la liste, ce qui est beaucoup moins sujet aux erreurs que de tenter de mettre à jour manuellement le fichier.
chaque fois que nous changeons le tableau sous-jacent.
Il est également intéressant de souligner que Knockout.js fait toujours le minimal quantité de modifications nécessaires pour synchroniser l'interface utilisateur. Au lieu de régénérer la liste complète chaque fois qu'un élément est ajouté ou supprimé, Knockout.js trace les parties du DOM concernées et les met à jour seulement ces éléments. Cette optimisation intégrée permet d’agrandir votre application en fonction de centaines voire de milliers d’articles sans sacrifier la réactivité..
Suppression d'éléments
De même, Knockout.js peut également supprimer des éléments d’un tableau observable via le retirer() méthode. Dans la définition de PersonViewModel, ajoutez une autre méthode pour supprimer des éléments:
this.removeProduct = fonction (produit) this.shoppingCart.remove (produit); ;
Ajoutez ensuite un bouton de suppression pour chaque élément de la liste. boucle:
Parce que nous sommes dans le pour chaque contexte, nous avons dû utiliser le $ root référence pour accéder à notre ViewModel au lieu de l’élément actuel de la boucle. Si nous avions essayé d'appeler removeProduct () sans cette référence, Knockout.js aurait tenté d'appeler la méthode sur la classe Product, qui n'existe pas. Tous les contextes de liaison disponibles pour foreach sont traités dans la leçon suivante..
Le fait que nous sommes dans un pour chaque la boucle gâche aussi le ce référence dans removeProduct (), donc en cliquant sur un Retirer Le bouton lancera une erreur TypeError. Nous pouvons utiliser une astuce JavaScript commune pour résoudre ce type de problèmes de portée. En haut de la définition de PersonViewModel, affectez-le à une nouvelle variable appelée self:
fonction PersonViewModel () var self = this;…
Ensuite, utilisez soi au lieu de ce dans la méthode removeProduct ():
this.removeProduct = fonction (produit) self.shoppingCart.remove (produit); ;
Vous devriez maintenant pouvoir manipuler notre tableau observable avec le Ajouter de la bière et Retirer boutons. Notez également que Knockout.js ajoute automatiquement l’élément actuel de la boucle en tant que premier paramètre à removeProduct ().
Détruire des objets
le retirer() Cette méthode est utile pour manipuler des listes en temps réel, mais elle peut s'avérer gênante lorsque vous essayez d'envoyer des données du ViewModel à un script côté serveur..
Par exemple, envisagez de sauvegarder le panier dans une base de données chaque fois que l'utilisateur ajoute ou supprime un article. Avec retirer(), l'article est retiré immédiatement, il vous suffit donc d'envoyer la nouvelle liste au serveur dans son intégralité. Il est impossible de déterminer quels éléments ont été ajoutés ou supprimés. Vous devez soit sauvegarder la liste complète, soit déterminer manuellement la différence entre la version précédente stockée dans la base de données et la nouvelle transmise par la demande AJAX..
Aucune de ces options n'est particulièrement efficace, d'autant plus que Knockout.js sait exactement quels éléments ont été supprimés. Pour remédier à cette situation, les tableaux observables incluent un détruire() méthode. Essayez de changer PersonViewModel.removeProduct () comme suit:
Maintenant, lorsque vous cliquez sur le Retirer bouton, Knockout.js habitude supprimez l'élément du tableau sous-jacent. Ceci est indiqué dans le message d'alerte, qui devrait ne pas diminuez lorsque vous cliquez sur «Supprimer». Au lieu de modifier la liste, le détruire() méthode ajoute un _détruire propriété du produit et le définit sur true. Vous pouvez afficher cette propriété en ajoutant un autre message d'alerte:
alert (product._destroy);
le _détruire Cette propriété permet de trier une liste observable et d'extraire uniquement les éléments supprimés. Ensuite, vous pouvez envoyer seulement ces éléments à un script côté serveur à supprimer. C'est un moyen beaucoup plus efficace de gérer les listes lorsque vous travaillez avec des requêtes AJAX.
Notez que le pour chaque boucle est consciente de cette convention et supprime toujours le code associé.
élément de la vue, même si l'élément reste dans le tableau sous-jacent.
Autres méthodes de tableau
En interne, les tableaux observables ressemblent aux propriétés normales observables, sauf qu'ils sont protégés par un tableau JavaScript natif au lieu d'une chaîne, d'un nombre ou d'un objet. Comme pour les variables observables normales, vous pouvez accéder à la valeur sous-jacente en appelant le tableau observable sans aucune propriété:
this.debugItems = function () var message = ""; var nativeArray = this.shoppingCart (); pour (var i = 0; i
L'appel de cette méthode parcourt les éléments de la liste native et donne également accès aux méthodes de tableau JavaScript natives telles que pousser(), pop(), shift (), sort (), etc.
Cependant, Knockout.js définit sa propre versions de ces méthodes sur l'objet tableau observable. Par exemple, plus tôt dans cette leçon, nous avons utilisé shoppingCart.push () ajouter un article au lieu de shoppingCart (). push (). Le premier appelle la version de Knockout.js, et le second appelle push () sur le tableau JavaScript natif.
Il est généralement préférable d'utiliser les méthodes de tableau de Knockout.js au lieu d'accéder directement au tableau sous-jacent, car cela permet à Knockout.js de mettre à jour automatiquement tous les composants de vue dépendants. Voici la liste complète des méthodes de tableaux observables fournies par Knockout.js. La plupart d'entre eux agissent exactement comme leurs homologues JavaScript natifs.
pousser()
pop()
décaler()
décalage()
tranche()
retirer()
Enlever tout()
détruire()
détruireTout()
Trier()
renversé()
Indice de()
Résumé
Dans cette leçon, nous avons vu comment les observables calculés peuvent être utilisés pour combiner des observables normaux en propriétés composées que Knockout.js peut suivre. Nous avons également utilisé des tableaux observables, qui permettent à Knockout.js de synchroniser des listes de données dans le ViewModel avec des composants HTML..
Ensemble, les observables atomiques, calculés et matriciels fournissent tous les types de données sous-jacents dont vous aurez besoin pour une interface utilisateur classique. Les objets observables calculés et les tableaux observables font de Knockout.js une excellente option pour le prototypage rapide. Ils vous permettent de placer toutes vos fonctionnalités complexes à un endroit donné, puis de laisser Knockout.js s'occuper du reste.
Par exemple, il serait trivial de créer un observable calculé qui calcule le prix total de chaque article dans le panier. chariot liste et l'affiche au bas de la page. Une fois que vous avez créé cette fonctionnalité, vous pouvez la réutiliser. nulle part vous avez besoin du prix total (par exemple, une demande AJAX) simplement en accédant à une propriété ViewModel.
La prochaine leçon présente les liaisons de contrôle. le pour chaque La liaison que nous avons utilisée dans cette leçon est probablement l'outil de flux de contrôle le plus courant, mais Knockout.js inclut également quelques liaisons supplémentaires pour un contrôle plus fin de nos composants de vue HTML..
Cette leçon représente un chapitre de Knockout Succinctly, un eBook gratuit de l'équipe de Syncfusion.