web-dev-qa-db-fra.com

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

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

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

Utiliser le débogueur Chrome me dit seulement:

"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?

196
RogierBessem

Une chose que je fais souvent quand il y a un problème avec quelles données sont disponibles à un certain périmètre est de remplacer le modèle/la 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 va cracher les données qui sont liées à cette portée et vous permettre de vous assurer que vous imbriquez les choses correctement. 

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.

338
RP Niemeyer

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 de Knockoutjs qui affiche le contexte de liaison directement dans le panneau Eléments des outils de développement.

60
neverfox

Définissez une fois bindingHandler , quelque part dans les fichiers de votre 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 aime ça:

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

Avantages

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

enter image description here

35
Dirk Boer

J'ai trouvé un autre qui peut être utile. Je déboguais certaines liaisons et essayais d'utiliser l'exemple de Ryans. J'ai eu une erreur 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>

Cependant, en utilisant cette approche, la valeur de liaison de données a été remplacée par la suivante:

  <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 alors que la fenêtre de débogage de chrome est ouverte, je reçois une fenêtre de variables de portée bien remplie.

J'ai trouvé un meilleur moyen pour cela:

<pre data-bind="text: ko.computed(function() { debugger; })"></pre>
32
RogierBessem

Guide étape par étape

  1. Pour ce guide, nous utiliserons l’un des exemples officiels de KnockoutJS .
  2. Supposons que vous souhaitiez voir les données derrière le deuxième contact (Sensei Miyagi).
  3. Cliquez avec le bouton droit de la souris sur la première zone de saisie du deuxième contact (celle contenant le texte "Sensei").
  4. Sélectionnez "Inspecter l'élément". La barre d'outils Chrome Developer va s'ouvrir.
  5. Ouvrez la fenêtre de la console JavaScript. Vous pouvez accéder à la console en cliquant sur l'icône >= dans le coin inférieur gauche de la barre d'outils Chrome Developer ou en ouvrant l'onglet "Console" dans la barre d'outils Chrome Developer 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 situé à gauche de l'objet pour parcourir 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 contenant tout le contexte de 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 différentes constructions.

Example output when following above guide

Quelle est cette magie noire?

Cette astuce est une combinaison de fonctionnalité $ 0- $ 4 de Chrome et méthodes utilitaires de KnockoutJS . En bref, Chrome mémorise les éléments que vous avez sélectionnés dans la barre d'outils Chrome Developer et les expose sous l'alias $0, $1, $2, $3, $4. Ainsi, lorsque vous cliquez avec le bouton droit de la souris sur un élément de votre navigateur et que vous 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.

Les méthodes utilitaires de KnockoutJS, ko.dataFor et ko.contextFor, constituent l’autre côté du tour:

  • ko.dataFor(element) - retourne les données disponibles pour être liées à l'élément
  • ko.contextFor(element) - renvoie l'intégralité du contexte de liaison 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é à la recherche de variables. Vous pouvez stocker la sortie de ko.contextFor et manipuler le modèle de vue directement à partir de la console. Essayez var root = ko.contextFor($0).$root; root.addContact(); et voyez ce qui se passe :-)

Bon débogage!

17
Martin Devillers

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

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

Ou 

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

Ensuite, en HTML, par exemple, 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 &AGRAVE; JOUR

Une autre chose gênante est lorsque vous essayez de vous lier à une valeur non définie. Imaginons, dans l'exemple ci-dessus, que l'objet de données est simplement {} et non {valeur: 'du texte'}. Dans ce cas, vous aurez des problèmes, mais avec le tweak suivant, tout ira bien:

<div data-bind="text: $data['value']"></div> 
7
Aleksey Bykov

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 une image du contexte de données sur ce nœud.

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

enter image description here

Nous remercions RP Niemeyer pour ses excellents échantillons de code Knockout sur SO pour que je puisse en venir à ce point.

5
Jon Kragh

Le moyen le plus simple pour voir quelles données sont passées à la liaison est de les déposer sur la console:

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

Knockout évalue la valeur de la liaison de texte (toute liaison peut être utilisée ici) et vide les données $ dans le panneau de navigation de la console.

3
Dmitry Pavlov

Si vous développez dans Visual studio et IE, j'aime plus ceci data-bind="somebinding:(function(){debugger; return bindvalue; })()". 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 pourrez simplement regarder le contexte $ $ data (je l’utilise aussi dans Chrome);

1
Filip Cordas

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

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

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

Code KO:

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

Cela mettra le code en pause dans le débogueur, et element et valueAccessor() contiendront des informations précieuses.

1
Aditya M P

Cela fonctionne pour moi: 

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