56 votes

Est-ce que j'abuse du plugin de mappage de Knockout en l'utilisant toujours pour mon viewmodel ?

Je suis toujours en train d'apprendre le bon usage de Knockout et je me suis vite éloigné de taper ko.observable lorsque je configure mon viewmodel et au lieu de cela, je définis juste un objet littéral et le passe à travers le plugin de mapping avec quelque chose comme

var viewModel = ko.mapping.fromJS(data);

ou au moins, quelque chose du genre de mettre toutes mes données dans un attribut sur le viewModel comme ceci

var viewModel = { 
    ... événements etc ... , 
    "data": ko.mapping.fromJS(data)
}

Pour être honnête, la principale raison pour laquelle je fais ça est d'éviter de taper ko.observable et ko.observableArray de manière répétitive. J'essaie juste de savoir si c'est une bonne approche et s'il y a des inconvénients à abandonner complètement la déclaration spécifique var x = ko.observable(). De plus, je fais tout ça au chargement, pas en réponse à un appel ajax, ce qui, d'après ce que je peux dire, est ce pour quoi le plugin de mapping a été conçu.

Dans votre travail avec knockout, déclarez-vous toujours les observables manuellement, un par un, ou avez-vous opté pour la méthode mapping.fromJS que j'utilise? Y a-t-il des inconvénients spécifiques à utiliser aussi fréquemment le plugin de mapping de cette manière?

Éditer :

Exemple spécifique

Dans cet article, Steve configure son viewModel en faisant

var initialData = [ { ... } , { ... } ]; // json du sérialiseur
var viewModel = {
    gifts : ko.observableArray(initialData)
};

Normalement, j'utiliserais simplement ko.mapping.fromJS pour cette situation également, spécifiquement pour m'assurer que les objets dans le tableau sont également transformés en observables. En regardant ce qu'il a fait, mon approche semble être exagérée et ajoute un peu de surcharge inutile.

59voto

Allen Rice Points 8899

Après l'utilisation de knock-out pour un peu plus de temps, j'ai remarqué que le plugin de cartographie a quelques options supplémentaires que vous donner beaucoup plus de précision, le contrôle sur le processus de cartographie.

Contrôle du type et de la quantité de propriétés généré

Il y a plusieurs façons de le faire, et je vais aller sur quelques-uns, mais le résultat final est que vous vous retrouvez avec une version plus légère de la cartographie plugin parce que tout n'est pas observable.

Fondamentalement, vous laissez tout ce que vous ne pensez pas que va changer, comme une propriété classique et faire seulement observables de l', des éléments spécifiques que vous voulez observer.

Faire mapping omettre certaines propriétés

Vous pouvez faire de la cartographie plugin omettre propriétés entièrement à partir de la fin résultat en spécifiant des choses comme ignore ou include. Ces deux accomplir la même chose, juste en face de moyens.

Remarque: les Échantillons sont de la knockout.js plugin de cartographie de la documentation, les commentaires ajoutés par moi

Plugin De Cartographie Argument: include

L'extrait de code suivant va omettre toutes les propriétés de l'objet source autres que celles qui sont passées par l' include argument.

// specify the specific properties to include as observables in the end result 
var mapping = {
    // only include these two properties
    'include': ["propertyToInclude", "alsoIncludeThis"]
}

// viewModel will now only contain the two properties listed above, 
//    and they will be observable
var viewModel = ko.mapping.fromJS(data, mapping);

Plugin De Cartographie Argument: ignore

Si vous voulez seulement omettre certaines propriétés de l'objet source, l'utilisation de l' ignore argument comme indiqué ci-dessous. Il fera observables à partir de toutes les propriétés de l'objet source, sauf pour les propriétés spécifiées.

// specify the specific properties to omit from the result, 
//    all others will be made observable
var mapping = {
    // only ignore these two properties
    'ignore': ["propertyToIgnore", "alsoIgnoreThis"]
}

// viewModel will now omit the two properties listed above, 
//    everything else will be included and they will be an observable
var viewModel = ko.mapping.fromJS(data, mapping);

Contrôle de quelles propriétés sont ou ne sont pas observables

Si vous avez besoin d'inclure des propriétés, mais vous ne pensez pas qu'ils doivent être faits observables (pour quelque raison que ce soit), la cartographie plugin a quelque chose qui peut aider.

Plugin De Cartographie Argument: copy

Si vous souhaitez que le plugin de cartographie de copier simplement la plaine de propriétés et de ne pas les rendre observables, l'utilisation de cet argument, comme indiqué ci-dessous.

// tell the mapping plugin to handle all other properties normally, 
//    but to simply copy this property instead of making it observable
var mapping = {
    'copy': ["propertyToCopy"]
}
var viewModel = ko.mapping.fromJS(data, mapping);

Prendre le contrôle complet sur le processus de cartographie

Si vous voulez avoir le contrôle à 100% sur ce qui est créé dans le processus de cartographie, notamment la possibilité de mettre des fermetures et des abonnements à vos objets, alors vous voulez utiliser l'option "créer".

plaine résultat avec des propriétés calculées

Voici un exemple où j'ai été de cartographie des données à partir d'un appel ajax vers un objet avec un results de la propriété. Je ne voulais plus rien observables et je voulais juste un simple généré propriété qui pourrait être faite de l'autre simple, les propriétés sur l'objet. Peut-être pas la plus convaincante exemple, mais il montre la fonctionnalité.

var searchMappingConfig = {
    // specific configuration for mapping the results property
    "results": {
                    // specific function to use to create the items in the results array
        "create": function (options) {
            // return a new function so we can have the proper scope/value for "this", below
            return new function () {

                // instead of mapping like we normally would: ko.mapping.fromJS(options.data, {}, this);
                // map via extend, this will just copy the properties from the returned json element to "this"
                // we'll do this for a more light weight vm since every last property will just be a plain old property instead of observable
                $.extend(this, options.data);

                // all this to add a vehicle title to each item
                this.vehicleTitle = this.Year + "<br />" + this.Make + " " + this.Model;
                }, this);
            };
        }
    }
}

abonnements et de la fermeture et de la cartographie, oh mon

Une autre situation est que si vous voulez des fermetures et des abonnements dans votre suite. Cet exemple est trop long pour être inclus dans son intégralité, mais pour un véhicule de la marque/le modèle de la hiérarchie. Je voulais tous les modèles (les enfants) pour un faire (parent) à être non-activé si le modèle n'a pas activé et je voulais que cela soit fait avec un abonnement.

// here we are specifying the way that items in the make array are created, 
//    since makes has a child array (Models), we will specify the way that 
//    items are created for that as well
var makesModelsMappingConfig = {
   // function that has the configuration for creating makes
   "create": function (options) {
      // return a new function so we can have the proper 
      //    scope/value for "this", below
      return new function () {

         // Note: we have a parent / child relationship here, makes have models. In the 
         //    UI we are selecting makes and then using that to allow the user to select 
         //    models. Because of this, there is going to be some special logic in here 
         //    so that all the child models under a given make, will automatically 
         //    unselect if the user unselects the parent make.

         // make the selected property a private variable so it can be closure'd over
         var makeIsSelected = ko.protectedComputed(false);

         // expose our property so we can bind in the UI
         this.isSelected = makeIsSelected;

         // ... misc other properties and events ...

         // now that we've described/configured how to create the makes, 
         //    describe/configure how to create the models under the makes
         ko.mapping.fromJS(options.data, {
            // specific configuration for the "Models" property                  
            "Models": {
               // function that has the configuration for creating items 
               //    under the Models property
               "create": function (model) {

                  // we'll create the isSelected as a local variable so 
                  //    that we can flip it in the subscription below, 
                  //    otherwise we wouldnt have access to flip it
                  var isSelected = ko.protectedComputed(false);

                  // subscribe to the parents "IsSelected" property so 
                  //    the models can select/unselect themselves
                  parentIsSelected.current.subscribe(function (value) {
                     // set the protected computed to the same 
                     //    value as its parent, note that this 
                     //    is just protected, not the actual value
                     isSelected(value);
                  });


                  // this object literal is what makes up each item 
                  //    in the Models observable array 
                  return {
                     // here we're returning our local variable so 
                     //    we can easily modify it in our subscription
                     "isSelected": isSelected,

                     // ... misc properties to expose 
                     //     under the item in the Model array ...

                  };
               }
            }
         }, this);
      };
   }
};

Dans l'ensemble, ce que j'ai trouvé, c'est que vous aurez rarement besoin de 100% de l'objet que vous d passer pour le plugin et vous aurez rarement besoin de 100% de celui-ci pour être observable. Creuser avec la cartographie des options de configuration et de créer toutes sortes de complexes et de simples objets. L'idée est d'obtenir tout ce dont vous avez besoin, rien de plus ou de moins.

22voto

photo_tom Points 4160

Ma suggestion pour vous serait la même qu'une autre question à laquelle je viens de répondre sur https://stackoverflow.com/questions/7499133/mapping-deeply-hierarchical-objects-to-custom-classes-using-knockout-mapping-plug.

Votre raisonnement pour utiliser le plug-in de mapping est raisonnable et c'est celui que j'utilise. Pourquoi taper plus de code que nécessaire?

Dans mon expérience avec knockout (seulement 4 mois), j'ai constaté que moins je fais manuellement et que je laisse les routines de knockout faire leur travail, meilleurs semblent fonctionner mes applications. Ma suggestion est d'essayer l'approche la plus simple d'abord. Si cela ne répond pas à vos besoins, regardez comment l'approche simple fait son "travail" et déterminez ce qui doit changer pour répondre à vos besoins.

4voto

Tom Hall Points 2090

Allen, mon expérience d'apprentissage récente avec Knockout.js a été similaire à la tienne. Nous travaillons avec un graphique d'objets hiérarchique profond provenant du serveur et j'ai défini des fonctions de modèle de vue explicitement instanciables qui préservent sa structure de base.

J'ai commencé par définir chaque propriété explicitement comme observable sur le modèle de vue pertinent, mais cela a rapidement dégénéré. De plus, une des principales raisons de passer à l'utilisation du plugin de mapping était que nous devions effectuer fréquemment des publications Ajax du graphique de retour vers le serveur où il est fusionné avec la version persistée, puis validé sur le serveur de telle manière que de nombreuses propriétés peuvent changer et les collections être modifiées, et une nouvelle instance retournée en tant que résultat Ajax où elle doit être à nouveau fusionnée avec la représentation client. Cela est devenu sérieusement difficile, et le plugin de mapping a beaucoup aidé en permettant la spécification d'identifiants pour résoudre les ajouts / suppressions / mises à jour et remapper un graphique mis à jour sur l'original.

Cela a également aidé dans la création du graphique original en utilisant l'option "create" pour les sous-modèles de vue. Dans chaque constructeur de modèle de vue, je reçois une référence au modèle de vue parent ainsi que les données avec lesquelles construire le modèle de vue enfant, puis crée d'autres options de mapping pour créer des petits-enfants à partir des données enfant passées.

Le seul (léger) inconvénient que j'ai récemment trouvé, comme détaillé dans cette question, est que lors de l'utilisation de ko.mapping.toJSON, il ne se connecte pas aux éventuels remplacements de toJSON que vous auriez définis sur les prototypes de vos modèles de vue afin d'exclure des propriétés de la sérialisation. J'ai pu contourner cela en spécifiant des options d'ignorance dans le démappage, comme recommandé par Ryan Niemeyer dans ce message.

En résumé, je vais certainement continuer d'utiliser le plugin de mapping. Knockout.js est génial.

1voto

George Mavritsakis Points 2778

Un module complémentaire plus simple mais utile pourrait être knockout-data-projections

Actuellement, il ne gère pas les mappages de JavaScript vers viewmodel, mais il gère plutôt bien les mappages du viewmodel vers le JavaScript.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X