Come eseguire il debug degli errori di associazione dei modelli per KnockoutJS?


199

Continuo ad avere problemi con i problemi di debug nei modelli KnockoutJS.

Supponiamo che io voglia associare una proprietà chiamata " items" ma nel modello faccio un refuso e associo alla proprietà (non esistente) " item".

L'uso del debugger di Chrome mi dice solo:

"item" is not defined.

Esistono strumenti, tecniche o stili di codifica che mi aiutano a ottenere maggiori informazioni sul problema dell'associazione?

Risposte:


344

Una cosa che faccio abbastanza spesso quando c'è un problema con quali dati sono disponibili in un determinato ambito è sostituire il modello / sezione con qualcosa del tipo:

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

Oppure, se desideri una versione leggermente più leggibile:

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

Questo sputerà i dati che sono vincolati a quell'ambito e ti permetterà di assicurarti di annidare le cose in modo appropriato.

Aggiornamento: a partire da KO 2.1 , puoi semplificarlo per:

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

Ora gli argomenti vengono passati a JSON.stringify.


ohh. Devo porre anche questa domanda. Utilizzato un pezzo di codice complicato per i dati console.log. Adesso è molto più facile.
AlfeG,

3
Devo pensare di più ai suggerimenti per il debug e magari fare un post sul blog. Un altro che viene in mente è fare iscrizioni manuali contro osservabili o osservabili calcolati per osservare il cambiamento dei valori. Come se namefosse un fatto osservabilename.subscribe(function(newValue) { console.log("name", newValue); });
RP Niemeyer,

1
Potrebbe essere perché questa risposta è relativamente vecchia, ma perché non usare console.log e sfruttare tutta la potenza del debugger per visualizzare le proprietà degli oggetti? Vedi ie: stackoverflow.com/a/16242988/647845
Dirk Boer

1
@DirkBoer - anche l'utilizzo di console.log può essere un ottimo modo. Molte volte voglio vedere i dati accanto ai miei elementi come in uno foreachscenario e trovo più facile da vedere sulla pagina all'interno del markup di rendering rilevante piuttosto che setacciare la console. Dipende solo dalla situazione. Alcuni altri miei pensieri qui: knockmeout.net/2013/06/… . Inoltre, potresti voler registrare una versione "pulita" nella tua associazione come console.log(ko.toJS(valueAccessor()).
RP Niemeyer,

1
@RuneJeppesen - Non sono sicuro del tipo di dati che stai serializzando, ma qualcosa del genere può aiutarti: knockmeout.net/2011/04/…
RP Niemeyer

61

Se stai utilizzando Chrome per lo sviluppo, esiste un'estensione davvero eccezionale (con la quale non sono affiliato) chiamata debugger di contesto Knockoutjs che ti mostra il contesto di associazione direttamente nel pannello Elementi degli strumenti di sviluppo.


3
Vorrei che Firefox o Firebug avessero questo. Qualcuno sa di una cosa del genere?
Patrick Szalapski il

Sembra che il supporto sia stato eliminato. Causa l'arresto anomalo di Chrome se si utilizza una struttura complessa di associazione dei dati. Non ha lavorato per nessuno dei miei progetti per circa un anno ormai.
Artico,

Mi dispiace ascoltarlo, anche se da tempo sono passato da KO a Ember.
Neverfox,

1
Funziona (principalmente) bene per me e ho alcune strutture davvero complesse. Non l'ho provato ma nelle Opzioni per l'estensione suggerisce: "Se si verificano arresti anomali, è probabile che tu abbia un modello di visualizzazione non serializzabile. Puoi disattivare la serializzazione". C'è una casella sotto il messaggio per disabilitare questa funzione.
Grinn,

enormemente utile all'istante, ty.
Andrew

37

Definisci un bindingHandler una volta , da qualche parte nei file della libreria JavaScript.

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

che semplicemente usarlo piace questo:

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

vantaggi

  • Usa tutta la potenza del debugger di Chrome, come Reveal in Elements Panel
  • Non è necessario aggiungere elementi personalizzati al DOM, solo per il debug

inserisci qui la descrizione dell'immagine


32

Ne ho trovato un altro che può essere utile. Stavo eseguendo il debug di alcuni binding e ho provato a usare l'esempio di Ryans. Ho ricevuto un errore che JSON ha trovato un ciclo circolare.

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

Utilizzando questo approccio, tuttavia, è stato sostituito il valore di associazione dei dati con il seguente:

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

Ora, se faccio clic sull'elemento PRE mentre la finestra di debug di Chrome è aperta, ottengo una finestra delle variabili dell'ambito ben riempita.

Trovato un modo leggermente migliore per farlo:

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

Veramente utile. Si sono verificati loop circolari knockout e problemi di markup del rasoio usando <pre data-bind = "text: ko.toJSON ($ data, null, 2)"> </pre>. Il <pre ... debugger> è una soluzione alternativa perfetta. Per qualche motivo gli input RAZOR come @ Html.CheckBox stavano rompendo ko.toJSON.
Artico,

20

Guida passo passo

  1. Per questa guida, utilizzeremo uno degli esempi ufficiali di KnockoutJS .
  2. Supponi di voler vedere i dati dietro il secondo contatto (Sensei Miyagi).
  3. Fare clic con il tasto destro del mouse sulla prima casella di input del secondo contatto (quella con il testo 'Sensei').
  4. Seleziona "Ispeziona elemento". Si aprirà la barra degli strumenti di sviluppo di Chrome.
  5. Apri la finestra della console JavaScript. Puoi accedere alla console facendo clic >=sull'icona nella parte inferiore sinistra della barra degli strumenti di sviluppo di Chrome, oppure aprendo la scheda "Console" nella barra degli strumenti di sviluppo di Chrome o premendo Ctrl+ Shift+J
  6. Digita il comando seguente e premi Invio: ko.dataFor($0)
  7. Ora dovresti vedere i dati associati alla seconda riga. È possibile espandere i dati premendo il piccolo triangolo a sinistra dell'oggetto per navigare nella struttura ad albero degli oggetti.
  8. Digita il comando seguente e premi Invio: ko.contextFor($0)
  9. Ora dovresti vedere un oggetto complesso che contiene l'intero contesto Knockout, incluso il root e tutti i genitori. Ciò è utile quando si scrivono espressioni di rilegatura complesse e si desidera sperimentare costrutti diversi.

Esempio di output quando si segue la guida sopra

Cos'è questa magia nera?

Questo trucco è una combinazione della funzione $ 0- $ 4 di Chrome e dei metodi di utilità di KnockoutJS . In breve, Chrome si ricorda quali elementi è stato selezionato nella Developer Toolbar Chrome ed espone questi elementi sotto lo pseudonimo $0, $1, $2, $3, $4. Pertanto, quando fai clic con il pulsante destro del mouse su un elemento nel browser e selezioni "Ispeziona elemento", questo elemento diventa automaticamente disponibile sotto l'alias $0. Puoi usare questo trucco con KnockoutJS, AngularJS, jQuery o qualsiasi altro framework JavaScript.

L'altro lato del trucco sono i metodi di utilità di KnockoutJS ko.dataFor e ko.contextFor:

  • ko.dataFor(element) - restituisce i dati disponibili per l'associazione all'elemento
  • ko.contextFor(element) - restituisce l'intero contesto di associazione disponibile per l'elemento DOM.

Ricorda che la console JavaScript di Chrome è un ambiente di runtime JavaScript completamente funzionale. Ciò significa che non sei limitato a guardare solo le variabili. È possibile memorizzare l'output ko.contextFore manipolare il viewmodel direttamente dalla console. Prova a var root = ko.contextFor($0).$root; root.addContact();vedere cosa succede :-)

Buon debug!


7

Scopri una cosa davvero semplice che uso:

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

O

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

Quindi in HTML, diciamo, hai avuto:

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

Basta sostituirlo con

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

Più avanzato:

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

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

Godere :)

AGGIORNARE

Un'altra cosa fastidiosa è quando stai cercando di associare un valore indefinito. Immagina nell'esempio sopra che l'oggetto dati sia solo {} non {value: 'some text'}. In questo caso sarai nei guai, ma con la seguente modifica andrà bene:

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


3

Il modo più semplice per vedere quali dati vengono passati all'associazione è di rilasciarli sulla console:

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

Knockout valuterà il valore per l'associazione del testo ( qualsiasi associazione può essere utilizzata qui in realtà ) e scarica $ data al pannello del browser della console.


2

Tutte le altre risposte funzioneranno alla grande, sto solo aggiungendo quello che mi piace fare:

Nella tua vista (supponendo che tu abbia già associato un ViewModel):

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

Codice a eliminazione diretta:

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

Ciò metterà in pausa il codice nel debugger elemente valueAccessor()conterrà informazioni preziose.


non è necessaria un'associazione personalizzata. Dai un'occhiata a stackoverflow.com/documentation/knockout.js/5066/…
Adam Wolski,

1
Sì, sono d'accordo che non è assolutamente necessario farlo in questo modo, volevo solo sottolineare che questo è uno stile di debug ... a tutti sembra piacere farlo a modo loro :)
Aditya MP

1

Se stai sviluppando in Visual Studio e IE, mi piace di più, data-bind="somebinding:(function(){debugger; return bindvalue; })()"mi piace di più, quindi la funzione echo poiché andrà allo script con tutti i binding piuttosto che il file eval e puoi semplicemente guardare $ context $ data (io uso anche in Chrome);


Scommetto che non ha nulla a che fare con Visual Studio o IE.
Serhiy,

@Serhiy Lo stesso con Chrome ma in Chrome penso che potresti accedere al file senza di esso Non penso che tu possa accedere al file in VS.
Filip Cordas,

0

Questo funziona per me:

<div data-bind="text: function(){ debugger; }()"></div>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.