Jak debugować błędy wiązania szablonu dla KnockoutJS?


199

Wciąż mam problemy z debugowaniem problemów w szablonach KnockoutJS.

Powiedz, że chcę powiązać z właściwością o nazwie „ items”, ale w szablonie robię literówkę i wiążę się z (nieistniejącą) właściwością „ item”.

Korzystanie z debugera Chrome mówi mi tylko:

"item" is not defined.

Czy istnieją narzędzia, techniki lub style kodowania, które pomagają mi uzyskać więcej informacji na temat problemu z wiązaniem?

Odpowiedzi:


344

Jedną z rzeczy, które robię dość często, gdy występuje problem z tym, jakie dane są dostępne w pewnym zakresie, jest zastąpienie szablonu / sekcji czymś takim jak:

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

Lub, jeśli chcesz nieco bardziej czytelną wersję:

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

Spowoduje to wyplenienie danych powiązanych w tym zakresie i pozwoli upewnić się, że odpowiednio zagnieżdżasz rzeczy.

Aktualizacja: od KO 2.1 możesz uprościć to do:

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

Teraz argumenty są przekazywane do JSON.stringify.


och Też muszę zadać to pytanie. Użyłem skomplikowanego fragmentu kodu do danych console.log. Teraz jest o wiele łatwiej.
— AlfeG

3
Muszę więcej pomyśleć o poradach dotyczących debugowania i być może opublikować post na blogu. Innym, który przychodzi na myśl, jest ręczne dokonywanie subskrypcji obserwowalnych lub obliczalnych obserwowalnych w celu obserwowania zmian wartości. Jakby namemożna zaobserwowaćname.subscribe(function(newValue) { console.log("name", newValue); });
— RP Niemeyer

1
Może dlatego, że ta odpowiedź jest stosunkowo stara, ale dlaczego nie skorzystać z console.log i wykorzystać pełną moc debugera do przeglądania właściwości obiektu? Patrz np .: stackoverflow.com/a/16242988/647845
— Dirk Boer

1
@DirkBoer - używanie konsoli.log może być również świetnym sposobem. Często jednak chcę widzieć dane obok moich elementów, jak w foreachscenariuszu, i łatwiej mi jest zobaczyć na stronie w obrębie odpowiedniego renderowanego znacznika niż przesuwać przez konsolę. Tylko zależy od sytuacji. Więcej moich przemyśleń tutaj: knockmeout.net/2013/06/… . Możesz również chcieć zalogować „czystą” wersję w swoim powiązaniu jak console.log(ko.toJS(valueAccessor()).
— RP Niemeyer

1
@RuneJeppesen - Nie jestem pewien, jakie dane szeregujesz, ale coś takiego może pomóc: knockmeout.net/2011/04/…
— RP Niemeyer

61

Jeśli używasz Chrome do programowania, istnieje naprawdę świetne rozszerzenie (z którym nie jestem powiązany) o nazwie Debugger kontekstowy Knockoutjs, który pokazuje kontekst wiązania bezpośrednio w panelu Elementy narzędzi programistycznych.


3
Chciałbym, żeby Firefox lub Firebug miał to. Ktoś wie o takiej rzeczy?
— Patrick Szalapski

Wygląda na to, że wsparcie zostało porzucone. Powoduje awarię chrome, jeśli używasz złożonej struktury powiązania danych. Od około roku nie pracuje dla żadnego z moich projektów.
— Arktyczny

Przykro mi to słyszeć, choć już dawno przeniosłem się z KO do Embera.
— neverfox

1
Działa (głównie) dobrze dla mnie i mam kilka naprawdę skomplikowanych struktur. Nie próbowałem tego, ale w Opcjach rozszerzenia sugeruje: „Jeśli wystąpią awarie, prawdopodobnie masz niemożliwy do serializacji model widoku. Możesz wyłączyć serializację”. Pod komunikatem znajduje się pole wyboru umożliwiające wyłączenie tej funkcji.
— Grinn,

niezwykle przydatne natychmiast, ty.
— Andrew

37

Zdefiniuj obiekt bindingHandler raz , gdzieś w plikach biblioteki JavaScript.

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

niż zwykłe użycie lubi to:

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

Zalety

  • Wykorzystaj pełną moc debugera Chrome, np Ujawnij w panelu elementów
  • Nie musisz dodawać niestandardowych elementów do DOM, tylko w celu debugowania

wprowadź opis zdjęcia tutaj


32

Znalazłem inny, który może być pomocny. Debugowałem niektóre powiązania i próbowałem na przykładzie Ryans. Wystąpił błąd polegający na tym, że JSON znalazł okrągłą pętlę.

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

Ale stosując to podejście zastąpiono wartość wiązania danych następującą:

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

Teraz, jeśli kliknę element PRE, mając otwarte okno debugowania chrome, otrzymam ładnie wypełnione okno zmiennych zakresu.

Znalazłem trochę lepszy sposób:

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

Naprawdę użyteczne. Wystąpiły problemy z nokautowymi okrągłymi pętlami i problemy ze znacznikami Razor przy użyciu <pre data-bind = "text: ko.toJSON ($ data, null, 2)"> </pre>. <Pre ... debugger> to idealne obejście. Z jakiegoś powodu dane wejściowe RAZOR, takie jak @ Html.CheckBox, łamały ko.toJSON.
— Arctic

20

Przewodnik krok po kroku

  1. W tym przewodniku wykorzystamy jeden z oficjalnych przykładów KnockoutJS .
  2. Powiedz, że chcesz zobaczyć dane za drugim kontaktem (Sensei Miyagi).
  3. Kliknij prawym przyciskiem myszy pierwsze pole wprowadzania drugiego kontaktu (ten z tekstem „Sensei”).
  4. Wybierz „Sprawdź element”. Otworzy się pasek narzędzi Chrome dla programistów.
  5. Otwórz okno konsoli JavaScript. Aby uzyskać dostęp do konsoli, kliknij >=ikonę w lewym dolnym rogu paska narzędzi dla programistów Chrome lub otwierając kartę „Konsola” na pasku narzędzi dla programistów Chrome lub naciskając Ctrl+Shift +J
  6. Wpisz następujące polecenie i naciśnij klawisz Enter: ko.dataFor($0)
  7. Powinieneś teraz zobaczyć dane powiązane z drugim rzędem. Możesz rozwinąć dane, naciskając mały trójkąt po lewej stronie obiektu, aby poruszać się po drzewie obiektów.
  8. Wpisz następujące polecenie i naciśnij klawisz Enter: ko.contextFor($0)
  9. Powinieneś teraz zobaczyć złożony obiekt, który zawiera cały kontekst Knockout, w tym root i wszystkich rodziców. Jest to przydatne, gdy piszesz złożone wyrażenia wiążące i chcesz eksperymentować z różnymi konstrukcjami.

Przykładowe dane wyjściowe po zastosowaniu powyższego przewodnika

Czym jest ta czarna magia?

Ta sztuczka jest połączeniem funkcji Chrome 0–4 USD i metod użyteczności KnockoutJS . W skrócie, Chrome zapamiętuje, które elementy zostały wybrane w Chrome Developer Toolbar i eksponuje te elementy pod pseudonimem $0, $1, $2, $3, $4. Więc kiedy klikniesz prawym przyciskiem myszy element w przeglądarce i wybierzesz „Sprawdź element”, ten element automatycznie stanie się dostępny pod aliasem$0 . Możesz użyć tej sztuczki w KnockoutJS, AngularJS, jQuery lub w dowolnym innym języku JavaScript.

Drugą stroną sztuczki są metody narzędziowe KnockoutJS ko.dataFor i ko.contextFor:

  • ko.dataFor(element) - zwraca dane, które były dostępne do powiązania z elementem
  • ko.contextFor(element) - zwraca cały kontekst wiązania, który był dostępny dla elementu DOM.

Pamiętaj, że konsola JavaScript Chrome to w pełni funkcjonalne środowisko wykonawcze JavaScript. Oznacza to, że nie jesteś ograniczony tylko do patrzenia na zmienne. Możesz przechowywać dane wyjściowe ko.contextFori manipulować viewmodelem bezpośrednio z konsoli. Spróbuj var root = ko.contextFor($0).$root; root.addContact();i zobacz, co się stanie :-)

Miłego debugowania!


7

Sprawdź naprawdę prostą rzecz, której używam:

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

Lub

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

Powiedzmy, że w html:

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

Po prostu zamień na

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

Bardziej zaawansowany:

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

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

Cieszyć się :)

AKTUALIZACJA

Inną irytującą rzeczą jest próba powiązania z nieokreśloną wartością. Wyobraź sobie w powyższym przykładzie, że obiekt danych to po prostu {} nie {wartość: „jakiś tekst”}. W takim przypadku będziesz mieć kłopoty, ale z następującymi poprawkami będziesz w porządku:

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


3

Najłatwiejszym sposobem sprawdzenia, jakie dane są przekazywane do wiązania, jest upuszczenie danych na konsolę:

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

Knockout oceni wartość wiązania tekstowego ( w rzeczywistości można tu użyć dowolnego powiązania ) i opróżni $ dane do panelu przeglądarki konsoli.


2

Wszystkie pozostałe odpowiedzi będą działać świetnie, dodam tylko to, co lubię:

W twoim widoku (zakładając, że już związałeś ViewModel):

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

Kod nokaut:

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

Spowoduje to wstrzymanie kodu w debuggerze elementi valueAccessor()będzie zawierać cenne informacje.


nie ma potrzeby niestandardowego wiązania. Spójrz na stackoverflow.com/documentation/knockout.js/5066/...
— Adam Wolski

1
Tak, zgadzam się, że nie ma takiej potrzeby, chciałem tylko zaznaczyć, że jest to jeden styl debugowania ... wydaje się, że wszyscy lubią robić to po swojemu :)
— poseł Aditya

1

Jeśli rozwijasz się w Visual Studio i IE podoba mi się to bardziej data-bind="somebinding:(function(){debugger; return bindvalue; })()", bardziej podoba mi się to niż funkcja echa, ponieważ przejdzie ona do skryptu ze wszystkimi powiązaniami, a nie do pliku eval i możesz po prostu spojrzeć na dane $ kontekst $ (używam to także w Chrome);


Założę się, że nie ma to nic wspólnego z Visual Studio lub IE.
— Serhiy

@Serhiy To samo z chrome, ale w chrome Myślę, że możesz uzyskać dostęp do pliku bez niego Nie sądzę, że możesz uzyskać dostęp do pliku w VS.
— Filip Cordas,

0

To działa dla mnie:

<div data-bind="text: function(){ debugger; }()"></div>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.