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?
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
.
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.
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
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>
>=
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+Jko.dataFor($0)
ko.contextFor($0)
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émentko.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!
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>
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
Nous remercions RP Niemeyer pour ses excellents échantillons de code Knockout sur SO pour que je puisse en venir à ce point.
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.
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);
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.
Cela fonctionne pour moi:
<div data-bind="text: function(){ debugger; }()"></div>