Comment déboguer les erreurs de liaison de modèle pour KnockoutJS?

199

Je continue d'avoir des problèmes avec les problèmes de débogage dans les modèles KnockoutJS.

Disons que je veux me lier à une propriété appelée " items" mais dans le modèle, je fais une faute de frappe et je me lie à la propriété (non existante) " item".

L'utilisation du débogueur Chrome ne me dit que:

"item" is not defined.

Existe-t-il des outils, des techniques ou des styles de codage qui m'aident à obtenir plus d'informations sur le problème de liaison?

RogierBessem
la source

Réponses:

344

Une chose que je fais assez souvent quand il y a un problème avec les données disponibles à une certaine portée est de remplacer le modèle / section par quelque chose comme:

<div data-bind="text: ko.toJSON($data)"></div>

Ou, si vous voulez une version légèrement plus lisible:

<pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre>

Cela crachera les données liées à cette étendue et vous permettra de vous assurer que vous imbriquez les choses de manière appropriée.

Mise à jour: à partir de KO 2.1 , vous pouvez le simplifier pour:

<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>

Maintenant, les arguments sont passés à JSON.stringify.

RP Niemeyer
la source
ohh. Je dois aussi poser cette question. Utilisé un morceau de code compliqué pour consoler les données du journal. Maintenant, c'est beaucoup plus facile.
AlfeG
3
Je dois penser davantage aux conseils de débogage et peut-être faire un article de blog. Un autre qui me vient à l'esprit est de faire des abonnements manuels contre des observables ou des observables calculés pour regarder les valeurs changer. Comme si namec'était un fait observablename.subscribe(function(newValue) { console.log("name", newValue); });
RP Niemeyer
1
Peut-être parce que cette réponse est relativement ancienne, mais pourquoi ne pas utiliser console.log et utiliser toute la puissance du débogueur pour afficher les propriétés des objets? Voir ie: stackoverflow.com/a/16242988/647845
Dirk Boer
1
@DirkBoer - l'utilisation de console.log peut également être un excellent moyen. Souvent, je veux voir les données à côté de mes éléments comme dans un foreachscénario et je trouve plus facile de voir sur la page dans le balisage rendu approprié que de parcourir la console. Tout dépend de la situation. Un peu plus de mes pensées ici: knockmeout.net/2013/06/… . En outre, vous souhaiterez peut-être enregistrer une version "propre" dans votre liaison comme console.log(ko.toJS(valueAccessor()).
RP Niemeyer
1
@RuneJeppesen - Je ne sais pas quel type de données vous sérialisez, mais quelque chose comme ça peut aider: knockmeout.net/2011/04/…
RP Niemeyer
61

Si vous utilisez Chrome pour le développement, il existe une très bonne extension (avec laquelle je ne suis pas affilié) appelée débogueur de contexte Knockoutjs qui vous montre le contexte de liaison directement dans le panneau Éléments des outils de développement.

Neverfox
la source
3
Je souhaite que Firefox ou Firebug l'ait. Quelqu'un sait une telle chose?
Patrick Szalapski
Le support semble avoir été supprimé. Chrome se bloque si vous utilisez une structure de liaison de données complexe. N'a travaillé pour aucun de mes projets depuis environ un an maintenant.
Arctic
Désolé de l'entendre, bien que je sois depuis longtemps passé de KO à Ember.
neverfox
1
Cela fonctionne (surtout) bien pour moi, et j'ai des structures vraiment complexes. Je ne l'ai pas essayé, mais dans les options de l'extension, il suggère: "Si vous rencontrez des plantages, vous avez probablement un modèle de vue non sérialisable. Vous pouvez désactiver la sérialisation." Il y a une case sous le message pour désactiver cette fonctionnalité.
Grinn
extrêmement utile instantanément, ty.
Andrew
37

Définissez un bindingHandler une fois , quelque part dans vos fichiers de bibliothèque JavaScript.

ko.bindingHandlers.debug = 
{
    init: function(element, valueAccessor) 
    {
        console.log( 'Knockoutbinding:' );
        console.log( element );
        console.log( ko.toJS(valueAccessor()) );
    }
};

que simplement l'utiliser, il aime ça:

<ul data-bind="debug: $data">

Les avantages

  • Utilisez toute la puissance du débogueur Chrome, comme Reveal dans Elements Panel
  • Vous n'avez pas besoin d'ajouter des éléments personnalisés à votre DOM, juste pour le débogage

entrez la description de l'image ici

Dirk Boer
la source
32

J'en ai trouvé un autre qui peut être utile. Je déboguais quelques liaisons et essayais d'utiliser l'exemple de Ryans. J'ai reçu une erreur indiquant que JSON a trouvé une boucle circulaire.

<ul class="list list-fix" data-bind="foreach: detailsView().tabs">
 <li>
   <pre data-bind="text: JSON.stringify(ko.toJS($parent), null, 2)"></pre>
   <a href="#" data-bind="click: $parent.setActiveTab, text: title"></a>
 </li>
</ul>

Mais, en utilisant cette approche, a remplacé la valeur de liaison de données par ce qui suit:

  <ul class="list list-fix" data-bind="foreach: detailsView().tabs">
    <li>
      <pre data-bind="text: 'click me', click: function() {debugger}"></pre>
      <a href="#" data-bind="click: $parent.setActiveTab, text: title"></a>
    </li>
  </ul>

Maintenant, si je clique sur l'élément PRE tout en ouvrant la fenêtre de débogage de chrome, j'obtiens une fenêtre de variables d'étendue bien remplie.

J'ai trouvé un peu mieux pour cela:

<pre data-bind="text: ko.computed(function() { debugger; })"></pre>
RogierBessem
la source
Vraiment utile. J'ai rencontré des boucles circulaires désactivées et des problèmes de balisage Razor en utilisant <pre data-bind = "text: ko.toJSON ($ data, null, 2)"> </pre>. Le <pré ... débogueur> est une solution de contournement parfaite. Pour une raison quelconque, les entrées RAZOR comme @ Html.CheckBox cassaient ko.toJSON.
Arctic
20

Guide étape par étape

  1. Pour ce guide, nous utiliserons l'un des exemples officiels de KnockoutJS .
  2. Dites que vous voulez voir les données derrière le deuxième contact (Sensei Miyagi).
  3. Cliquez avec le bouton droit sur la première zone de saisie du deuxième contact (celui avec le texte «Sensei»).
  4. Sélectionnez «Inspecter l'élément». La barre d'outils des développeurs Chrome s'ouvre.
  5. Ouvrez la fenêtre de la console JavaScript. Vous pouvez accéder à la console en cliquant sur l' >=icône en bas à gauche de la barre d'outils du développeur Chrome, ou en ouvrant l'onglet "Console" dans la barre d'outils du développeur Chrome, ou en appuyant sur Ctrl+ Shift+J
  6. Tapez la commande suivante et appuyez sur Entrée: ko.dataFor($0)
  7. Vous devriez maintenant voir les données liées à la deuxième ligne. Vous pouvez développer les données en appuyant sur le petit triangle à gauche de l'objet pour naviguer dans l'arborescence des objets.
  8. Tapez la commande suivante et appuyez sur Entrée: ko.contextFor($0)
  9. Vous devriez maintenant voir un objet complexe qui contient tout le contexte Knockout, y compris la racine et tous les parents. Cela est utile lorsque vous écrivez des expressions de liaison complexes et que vous souhaitez expérimenter avec différentes constructions.

Exemple de sortie en suivant le guide ci-dessus

Quelle est cette magie noire?

Cette astuce est une combinaison de la fonctionnalité $ 0- $ 4 de Chrome et des méthodes utilitaires de KnockoutJS . Bref, Chrome se souvient que les éléments que vous avez sélectionné dans la barre d' outils Chrome Developer et expose ces éléments sous l'alias $0, $1, $2, $3, $4. Ainsi, lorsque vous cliquez avec le bouton droit sur un élément dans votre navigateur et sélectionnez «Inspecter l'élément», cet élément devient automatiquement disponible sous l'alias $0. Vous pouvez utiliser cette astuce avec KnockoutJS, AngularJS, jQuery ou tout autre framework JavaScript.

L'autre côté de l'astuce est les méthodes utilitaires de KnockoutJS ko.dataFor et ko.contextFor:

  • ko.dataFor(element) - renvoie les données disponibles pour la liaison avec l'élément
  • ko.contextFor(element) - renvoie l'intégralité du contexte de liaison qui était disponible pour l'élément DOM.

N'oubliez pas que la console JavaScript de Chrome est un environnement d'exécution JavaScript entièrement fonctionnel. Cela signifie que vous n'êtes pas limité à regarder uniquement les variables. Vous pouvez stocker la sortie ko.contextForet manipuler le viewmodel directement depuis la console. Essayez de var root = ko.contextFor($0).$root; root.addContact();voir ce qui se passe :-)

Bon débogage!

Martin Devillers
la source
7

Découvrez une chose vraiment simple que j'utilise:

function echo(whatever) { debugger; return whatever; }

Ou

function echo(whatever) { console.log(whatever); return whatever; }

Ensuite, en html, disons, vous aviez:

<div data-bind="text: value"></div>

Il suffit de le remplacer par

<div data-bind="text: echo(value)"></div>

Plus avancé:

function echo(vars, member) { console.log(vars); debugger; return vars[0][member]; }

<div data-bind="text: echo([$data, $root, $parents, $parentContext], 'value')"></div>

Prendre plaisir :)

METTRE À JOUR

Une autre chose ennuyeuse est lorsque vous essayez de vous lier à une valeur indéfinie. Imaginez dans l'exemple ci-dessus que l'objet de données est simplement {} pas {value: 'some text'}. Dans ce cas, vous aurez des ennuis, mais avec le réglage suivant, tout ira bien:

<div data-bind="text: $data['value']"></div> 
Trident D'Gao
la source
5

J'ai créé un projet github appelé knockthrough.js pour aider à visualiser ces erreurs.

https://github.com/JonKragh/knockthrough

Il met en évidence les erreurs de liaison et donne un vidage du contexte de données sur ce nœud.

Vous pouvez jouer avec un échantillon ici: http://htmlpreview.github.io/?https://github.com/JonKragh/knockthrough/blob/master/default.htm

entrez la description de l'image ici

Nous remercions RP Niemeyer pour ses excellents échantillons de code Knockout sur SO pour m'amener à ce point.

Jon Kragh
la source
3

Le moyen le plus simple de voir quelles données sont transmises à la liaison est de supprimer les données sur la console:

<div data-bind="text: console.log($data)"></div>

Knockout évaluera la valeur de la liaison de texte ( toute liaison peut être utilisée ici en fait ) et vide les données $ dans le panneau du navigateur de la console.

Dmitry Pavlov
la source
2

Toutes les autres réponses fonctionneront très bien, j'ajoute juste ce que j'aime faire:

Selon vous (en supposant que vous avez déjà lié un ViewModel):

<div data-bind="debugger: $data"></div>

Code de coupure:

ko.bindingHandlers.debugger = {
    init: function (element, valueAccessor) {
        debugger;
    }
}

Cela mettra le code en pause dans le débogueur elementet valueAccessor()contiendra des informations précieuses.

Aditya MP
la source
il n'y a pas besoin d'une reliure personnalisée. Jetez un œil à stackoverflow.com/documentation/knockout.js/5066/…
Adam Wolski
1
Oui, je suis d'accord qu'il n'y a pas vraiment besoin de le faire de cette façon, je voulais simplement souligner qu'il s'agit d'un style de débogage ... tout le monde semble aimer le faire à sa manière :)
Aditya MP
1

Si vous développez dans Visual studio et IE, j'aime plus data-bind="somebinding:(function(){debugger; return bindvalue; })()"ça, je l'aime plus que la fonction echo car il ira au script avec toutes les liaisons plutôt que le fichier eval et vous pouvez simplement regarder les données $ context $ (j'utilise cela dans Chrome également);

Filip Cordas
la source
Je parie que cela n'a rien à voir avec Visual Studio ou IE.
Serhiy
@Serhiy Idem avec chrome mais en chrome Je pense que vous pourriez accéder au fichier sans lui, je ne pense pas que vous puissiez accéder au fichier en VS.
Filip Cordas
0

Cela fonctionne pour moi:

<div data-bind="text: function(){ debugger; }()"></div>
Robert J
la source