Bagaimana cara debug kesalahan pengikatan template untuk KnockoutJS?

199

Saya terus mengalami masalah dengan masalah debugging di templat KnockoutJS.

Katakanlah saya ingin mengikat ke properti yang disebut " items" tetapi dalam template saya membuat kesalahan ketik dan mengikat ke properti (tidak ada) " item".

Menggunakan debugger Chrome hanya memberi tahu saya:

"item" is not defined.

Apakah ada alat, teknik, atau gaya pengkodean yang membantu saya mendapatkan informasi lebih lanjut tentang masalah yang mengikat?

RogierBessem
sumber

Jawaban:

344

Satu hal yang sering saya lakukan ketika ada masalah dengan data apa yang tersedia pada lingkup tertentu adalah mengganti templat / bagian dengan sesuatu seperti:

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

Atau, jika Anda ingin versi yang sedikit lebih mudah dibaca:

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

Ini akan memuntahkan data yang sedang terikat pada ruang lingkup itu dan membiarkan Anda memastikan bahwa Anda bersarang dengan tepat.

Pembaruan: pada KO 2.1 , Anda dapat menyederhanakannya menjadi:

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

Sekarang argumen diteruskan ke JSON.stringify.

RP Niemeyer
sumber
ohh Saya perlu menanyakan pertanyaan ini juga. Menggunakan potongan kode yang rumit untuk data console.log. Sekarang jauh lebih mudah.
AlfeG
3
Saya harus memikirkan lebih lanjut tentang tips debugging dan mungkin membuat posting blog. Satu lagi yang terlintas dalam pikiran adalah melakukan langganan manual terhadap yang dapat diobservasi atau yang dapat diobservasi untuk menyaksikan perubahan nilai. Seperti jika nameadalah tindakan yang dapat diamatiname.subscribe(function(newValue) { console.log("name", newValue); });
RP Niemeyer
1
Mungkin karena jawaban ini relatif lama, tetapi mengapa tidak menggunakan console.log dan memanfaatkan kekuatan penuh debugger untuk melihat properti objek? Lihat yaitu: stackoverflow.com/a/16242988/647845
Dirk Boer
1
@DirkBoer - menggunakan console.log bisa menjadi cara yang bagus juga. Banyak kali saya ingin melihat data di sebelah elemen saya seperti dalam foreachskenario dan saya merasa lebih mudah untuk melihat pada halaman dalam markup yang diberikan relevan daripada menyaring melalui konsol. Tergantung situasinya saja. Beberapa lagi pemikiran saya di sini: knockmeout.net/2013/06/… . Juga, Anda mungkin ingin mencatat versi "bersih" di binding seperti Anda console.log(ko.toJS(valueAccessor()).
RP Niemeyer
1
@RuneJeppesen - Saya tidak yakin data seperti apa yang Anda serialkan
RP Niemeyer
61

Jika Anda menggunakan Chrome untuk pengembangan, ada ekstensi yang sangat bagus (yang saya tidak berafiliasi) yang disebut debugger konteks Knockoutjs yang menunjukkan kepada Anda konteks yang mengikat langsung di panel Elemen Alat Pengembang.

tidak pernah
sumber
3
Saya berharap Firefox atau Firebug punya ini. Adakah yang tahu hal seperti itu?
Patrick Szalapski
Muncul dukungan telah dijatuhkan. Menyebabkan chrome mogok jika Anda menggunakan struktur ikatan data yang kompleks. Belum bekerja untuk proyek saya selama sekitar satu tahun sekarang.
Arktik
Maaf mendengarnya, meskipun saya sudah lama pindah dari KO ke Ember.
pernah
1
Ini bekerja (kebanyakan) baik untuk saya, dan saya memiliki beberapa struktur yang sangat kompleks. Saya belum mencobanya tetapi dalam Opsi untuk ekstensi itu menyarankan, "Jika Anda mengalami crash, Anda mungkin memiliki model view yang tidak berseri. Anda dapat mematikan serialisasi." Ada kotak centang di bawah pesan untuk menonaktifkan fitur ini.
Grinn
sangat berguna secara instan, ty.
Andrew
37

Tetapkan Handler handler sekali , di suatu tempat di file perpustakaan JavaScript Anda.

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

daripada hanya menggunakannya suka ini:

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

Keuntungan

  • Gunakan kekuatan penuh debugger Chrome, seperti Reveal in Elements Panel
  • Anda tidak harus menambahkan elemen khusus ke DOM Anda, hanya untuk debugging

masukkan deskripsi gambar di sini

Dirk Boer
sumber
32

Saya menemukan satu lagi yang dapat membantu. Saya sedang men-debug beberapa binding dan mencoba menggunakan contoh Ryans. Saya mendapat kesalahan bahwa JSON menemukan lingkaran lingkaran.

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

Namun, menggunakan pendekatan ini menggantikan nilai data-bind dengan yang berikut:

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

Sekarang jika saya klik pada elemen PRE sambil membuka jendela debug krom, saya mendapatkan jendela variabel lingkup terisi dengan baik.

Menemukan cara yang lebih baik untuk itu:

<pre data-bind="text: ko.computed(function() { debugger; })"></pre>
RogierBessem
sumber
Sangat bermanfaat. Sedang menemui loop melingkar knockout dan masalah marka Razor menggunakan <pre data-bind = "text: ko.toJSON ($ data, null, 2)"> </pre>. <Pre ... debugger> adalah solusi yang sempurna. Entah mengapa input RAZOR seperti @ Html.CheckBox melanggar ko.toJSON.
Arktik
20

Panduan langkah demi langkah

  1. Untuk panduan ini, kami akan menggunakan salah satu contoh KnockoutJS resmi .
  2. Katakanlah Anda ingin melihat data di balik kontak kedua (Sensei Miyagi).
  3. Klik kanan kotak input pertama dari kontak kedua (satu dengan teks 'Sensei').
  4. Pilih 'Periksa elemen'. Bilah Alat Pengembang Chrome akan terbuka.
  5. Buka jendela Konsol JavaScript. Anda dapat mengakses konsol dengan mengeklik >=ikon di kiri bawah Toolbar Pengembang Chrome, atau dengan membuka tab "Konsol" di Toolbar Pengembang Chrome, atau dengan menekan Ctrl+ Shift+J
  6. Ketikkan perintah berikut dan tekan Enter: ko.dataFor($0)
  7. Anda sekarang harus melihat data yang terikat ke baris kedua. Anda dapat memperluas data dengan menekan segitiga kecil di kiri Obyek untuk menavigasi pohon objek.
  8. Ketikkan perintah berikut dan tekan Enter: ko.contextFor($0)
  9. Sekarang Anda akan melihat objek kompleks yang berisi seluruh konteks Knockout termasuk root dan semua orang tua. Ini berguna ketika Anda menulis ekspresi yang mengikat kompleks dan Anda ingin bereksperimen dengan konstruksi yang berbeda.

Contoh output saat mengikuti panduan di atas

Apa ini ilmu hitam?

Trik ini adalah kombinasi fitur Chrome $ 0- $ 4 dan metode utilitas KnockoutJS . Singkatnya, Chrome mengingat unsur-unsur yang telah Anda pilih di Chrome Developer Toolbar dan mengekspos elemen ini di bawah alias $0, $1, $2, $3, $4. Jadi ketika Anda mengklik kanan sebuah elemen di browser Anda dan memilih 'Periksa elemen', elemen ini secara otomatis tersedia di bawah alias$0 . Anda dapat menggunakan trik ini dengan KnockoutJS, AngularJS, jQuery atau kerangka JavaScript lainnya.

Sisi lain dari trik ini adalah metode utilitas KnockoutJS yaitu ko.dataFor dan ko.contextFor:

  • ko.dataFor(element) - mengembalikan data yang tersedia untuk mengikat elemen
  • ko.contextFor(element) - mengembalikan seluruh konteks yang mengikat yang tersedia untuk elemen DOM.

Ingat, Konsol JavaScript Chrome adalah lingkungan runtime JavaScript yang berfungsi penuh. Ini berarti Anda tidak terbatas hanya dengan melihat variabel. Anda dapat menyimpan output ko.contextFordan memanipulasi model view langsung dari konsol. Coba var root = ko.contextFor($0).$root; root.addContact();dan lihat apa yang terjadi :-)

Selamat men-debug!

Martin Devillers
sumber
7

Lihatlah hal yang sangat sederhana yang saya gunakan:

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

Atau

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

Kemudian dalam html, katakanlah, Anda memiliki:

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

Ganti saja dengan

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

Lebih maju:

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

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

Nikmati :)

MEMPERBARUI

Hal lain yang menjengkelkan adalah ketika Anda mencoba untuk mengikat ke nilai yang tidak ditentukan. Bayangkan dalam contoh di atas bahwa objek data hanya {} bukan {value: 'some text'}. Dalam hal ini Anda akan berada dalam masalah, tetapi dengan tweak berikut Anda akan baik-baik saja:

<div data-bind="text: $data['value']"></div> 
Trident D'Gao
sumber
3

Cara termudah untuk melihat data apa yang diteruskan ke pengikatan adalah dengan menjatuhkan data ke konsol:

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

Knockout akan mengevaluasi nilai untuk pengikatan teks (pengikatan apa pun sebenarnya dapat digunakan di sini ) dan mem-flush $ data ke konsol panel browser.

Dmitry Pavlov
sumber
2

Semua jawaban lain akan bekerja dengan baik, saya hanya menambahkan apa yang ingin saya lakukan:

Dalam pandangan Anda (dengan asumsi Anda sudah terikat ViewModel):

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

Kode KO:

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

Ini akan menjeda kode dalam debugger, dan elementdan valueAccessor()akan berisi informasi berharga.

Aditya MP
sumber
tidak perlu ada pengikatan khusus. Lihatlah stackoverflow.com/documentation/knockout.js/5066/…
Adam Wolski
1
Yap, saya setuju tidak ada kebutuhan yang pasti untuk melakukannya dengan cara ini, saya hanya ingin menunjukkan bahwa ini adalah gaya debugging ... semua orang sepertinya suka melakukannya dengan cara mereka sendiri :)
Aditya MP
1

Jika Anda mengembangkan di Visual studio dan IE saya suka ini lebih data-bind="somebinding:(function(){debugger; return bindvalue; })()"saya menyukainya lebih dari itu fungsi gema karena itu akan pergi ke script dengan semua ikatan bukan file eval dan Anda bisa melihat $ konteks $ data (saya menggunakan ini di Chrome juga);

Filip Cordas
sumber
Saya yakin itu tidak ada hubungannya dengan Visual Studio atau IE.
Serhiy
@ Serhiy Sama dengan chrome tetapi di chrome saya pikir Anda bisa mengakses file tanpa itu saya tidak berpikir Anda dapat mengakses file dalam VS.
Filip Cordas
0

Ini bekerja untuk saya:

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