วิธีการดีบักข้อผิดพลาดการผูกแม่แบบสำหรับ KnockoutJS?


199

ฉันมีปัญหาในการแก้ไขข้อบกพร่องในแม่แบบ KnockoutJS

ว่าฉันต้องการผูกกับคุณสมบัติที่เรียกว่า " items" แต่ในเทมเพลตฉันพิมพ์ผิดและผูกเข้ากับคุณสมบัติ (ไม่มีอยู่) " item"

การใช้ดีบักเกอร์ Chrome บอกฉันเท่านั้น:

"item" is not defined.

มีเครื่องมือเทคนิคหรือรูปแบบการเข้ารหัสที่ช่วยให้ฉันได้รับข้อมูลเพิ่มเติมเกี่ยวกับปัญหาการผูกหรือไม่

คำตอบ:


344

สิ่งหนึ่งที่ฉันทำบ่อยๆเมื่อมีปัญหากับข้อมูลที่มีอยู่ในขอบเขตที่แน่นอนคือการแทนที่เทมเพลต / ส่วนด้วยสิ่งที่ชอบ:

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

หรือถ้าคุณต้องการรุ่นที่อ่านง่ายขึ้นอีกเล็กน้อย:

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

สิ่งนี้จะคายข้อมูลที่ถูกผูกไว้ที่ขอบเขตนั้นและให้คุณตรวจสอบให้แน่ใจว่าคุณกำลังซ้อนสิ่งต่างๆอย่างเหมาะสม

อัปเดต: ตั้งแต่ KO 2.1คุณสามารถทำให้เป็น:

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

JSON.stringifyตอนนี้ข้อโต้แย้งที่มีการส่งต่อไปยัง


โอ๋ ฉันต้องถามคำถามนี้ด้วย ใช้โค้ดที่ซับซ้อนเพื่อ data.log console.log ตอนนี้มันง่ายกว่ามาก
AlfeG

3
ฉันต้องคิดเพิ่มเติมเกี่ยวกับการแก้จุดบกพร่องเคล็ดลับและอาจทำให้โพสต์บล็อก อีกสิ่งหนึ่งที่อยู่ในใจคือการสมัครสมาชิกกับสิ่งที่สังเกตได้หรือสิ่งที่คำนวณได้เพื่อดูค่าที่เปลี่ยนแปลง เช่นถ้าnameเป็นการสังเกตได้name.subscribe(function(newValue) { console.log("name", newValue); });
RP Niemeyer

1
อาจเป็นเพราะคำตอบนี้ค่อนข้างเก่า แต่ทำไมไม่ใช้ console.log และใช้ประโยชน์จาก debugger ให้เต็มเพื่อดูคุณสมบัติของวัตถุ ดูเช่น: stackoverflow.com/a/16242988/647845
Dirk Boer

1
@DirkBoer - การใช้ console.log อาจเป็นวิธีที่ยอดเยี่ยมเช่นกัน หลายครั้งที่ฉันต้องการดูข้อมูลที่อยู่ถัดจากองค์ประกอบของฉันเช่นในforeachสถานการณ์และฉันพบว่ามันง่ายกว่าที่จะเห็นในหน้าภายในมาร์กอัปที่แสดงผลที่เกี่ยวข้องมากกว่าลอดผ่านคอนโซล ขึ้นอยู่กับสถานการณ์ เพิ่มเติมบางส่วนของความคิดของฉันที่นี่: knockmeout.net/2013/06/... นอกจากนี้คุณอาจต้องการที่จะเข้าสู่ระบบรุ่น "สะอาด" console.log(ko.toJS(valueAccessor())ในผลผูกพันของคุณเช่น
RP Niemeyer

1
@RuneJeppesen - ฉันไม่แน่ใจว่าข้อมูลแบบใดที่คุณกำลังซีเรียลไลซ์
RP Niemeyer

61

หากคุณกำลังใช้ Chrome เพื่อการพัฒนามีส่วนขยายที่ยอดเยี่ยมมาก (ซึ่งฉันไม่ได้อยู่ในเครือ) เรียกว่าดีบักเกอร์บริบท Knockoutjsที่แสดงบริบทการเชื่อมโยงให้คุณโดยตรงในแผงองค์ประกอบเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์


3
ฉันหวังว่า Firefox หรือ Firebug มีสิ่งนี้ ใครรู้เรื่องนี้บ้าง
Patrick Szalapski

การสนับสนุนปรากฏขึ้นถูกทิ้งไปแล้ว ทำให้โครเมียมหยุดทำงานหากคุณใช้โครงสร้างผูกข้อมูลที่ซับซ้อน ไม่ได้ทำงานให้กับโครงการใด ๆ ของฉันเป็นเวลาประมาณปี
Arctic

ขออภัยที่ได้ยินแม้ว่าฉันจะย้ายมาจาก KO เป็น Ember มานานแล้ว
neverfox

1
มันใช้งานได้ดี (ส่วนใหญ่) สำหรับฉันและฉันมีโครงสร้างที่ซับซ้อนจริง ๆ ฉันยังไม่ได้ลอง แต่ในตัวเลือกสำหรับส่วนขยายมันแนะนำ "ถ้าคุณประสบปัญหาคุณอาจมีรูปแบบที่ไม่ต่อเนื่องกันคุณสามารถปิดการทำให้เป็นอนุกรมได้" มีช่องทำเครื่องหมายด้านล่างข้อความสำหรับปิดใช้งานคุณสมบัตินี้
Grinn

มีประโยชน์มหาศาลทันที
Andrew

37

กำหนด bindingHandler หนึ่งครั้งที่ใดที่หนึ่งในไฟล์ไลบรารี JavaScript ของคุณ

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

กว่าใช้เพียงแค่ชอบสิ่งนี้:

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

ข้อดี

  • ใช้พลังเต็มที่ของตัวดีบัก Chrome เช่นเปิดเผยในแผงองค์ประกอบ
  • คุณไม่จำเป็นต้องเพิ่มองค์ประกอบที่กำหนดเองใน DOM ของคุณเพียงแค่ทำการดีบั๊ก

ป้อนคำอธิบายรูปภาพที่นี่


32

ฉันพบอีกอันที่สามารถช่วยเหลือได้ ฉันแก้จุดบกพร่องและพยายามใช้ตัวอย่างของ Ryans ฉันพบข้อผิดพลาดที่ JSON พบลูปวงกลม

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

แต่การใช้วิธีการนี้จะเป็นการแทนที่ค่า data-bind ด้วยค่าต่อไปนี้:

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

ตอนนี้ถ้าฉันคลิกที่องค์ประกอบ PRE ในขณะที่เปิดหน้าต่าง debug ของ Chrome ฉันจะได้รับหน้าต่างตัวแปรขอบเขต

พบวิธีที่ดีกว่าเล็กน้อยสำหรับมัน:

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

มีประโยชน์จริงๆ พบปัญหาลูปแบบวนรอบที่น่าพิศวงและปัญหามาร์คอัปของมีดโกนโดยใช้ <pre data-bind = "text: ko.toJSON ($ data, null, 2)"> </pre> <pre ... ดีบักเกอร์> เป็นวิธีการแก้ปัญหาที่สมบูรณ์แบบ ด้วยเหตุผลบางประการอินพุตของ RAZOR เช่น @ Html.CheckBox กำลังทำลาย ko.toJSON
Arctic

20

คู่มือทีละขั้นตอน

  1. สำหรับคู่มือนี้เราจะใช้หนึ่งในตัวอย่าง KnockoutJS อย่างเป็นทางการ
  2. สมมติว่าคุณต้องการดูข้อมูลเบื้องหลังการติดต่อครั้งที่สอง (Sensei Miyagi)
  3. คลิกขวาที่กล่องป้อนข้อมูลแรกของผู้ติดต่อรายที่สอง (กล่องที่มีข้อความ 'อาจารย์')
  4. เลือก 'ตรวจสอบองค์ประกอบ' แถบเครื่องมือนักพัฒนาซอฟต์แวร์ Chrome จะเปิดขึ้น
  5. เปิดหน้าต่างคอนโซล JavaScript คุณสามารถเข้าถึงคอนโซลได้โดยคลิกที่>=ไอคอนด้านล่างซ้ายของแถบเครื่องมือนักพัฒนาซอฟต์แวร์ Chrome หรือโดยการเปิดแท็บ "คอนโซล" ในแถบเครื่องมือนักพัฒนาซอฟต์แวร์ Chrome หรือกดCtrl+ Shift+J
  6. พิมพ์คำสั่งต่อไปนี้แล้วกด Enter: ko.dataFor($0)
  7. ตอนนี้คุณควรเห็นข้อมูลที่ถูกผูกไว้กับแถวที่สอง คุณสามารถขยายข้อมูลโดยการกดสามเหลี่ยมเล็ก ๆ ด้านซ้ายของวัตถุเพื่อนำทางโครงสร้างวัตถุ
  8. พิมพ์คำสั่งต่อไปนี้แล้วกด Enter: ko.contextFor($0)
  9. ตอนนี้คุณควรเห็นวัตถุซับซ้อนที่มีบริบทที่น่าพิศวงทั้งรากและผู้ปกครองทั้งหมด สิ่งนี้มีประโยชน์เมื่อคุณเขียนนิพจน์การเชื่อมโยงที่ซับซ้อนและคุณต้องการทดสอบโครงสร้างที่แตกต่างกัน

ตัวอย่างผลลัพธ์เมื่อทำตามคำแนะนำด้านบน

เวทมนตร์สีดำนี้คืออะไร?

เคล็ดลับนี้เป็นชุดของของ Chrome $ 0- $ 4 คุณลักษณะและKnockoutJS ของวิธีการยูทิลิตี้ ในระยะสั้น Chrome จะจำได้ว่าองค์ประกอบใดที่คุณได้เลือกใน Chrome Developer Toolbar และตีแผ่องค์ประกอบเหล่านี้ภายใต้นามแฝง$0, $1, $2, ,$3 $4ดังนั้นเมื่อคุณคลิกขวาที่องค์ประกอบในเบราว์เซอร์ของคุณและเลือก 'ตรวจสอบองค์ประกอบ' $0องค์ประกอบนี้โดยอัตโนมัติกลายเป็นใช้ได้ภายใต้นามแฝง คุณสามารถใช้เคล็ดลับนี้กับ KnockoutJS, AngularJS, jQuery หรือเฟรมเวิร์ก JavaScript อื่น ๆ

อีกด้านของเคล็ดลับคือวิธีการใช้ประโยชน์ของ KnockoutJS ko.dataFor และ ko.contextFor:

  • ko.dataFor(element) - ส่งคืนข้อมูลที่พร้อมสำหรับการเชื่อมโยงกับองค์ประกอบ
  • ko.contextFor(element) - ส่งคืนบริบทการเชื่อมโยงทั้งหมดที่มีให้กับองค์ประกอบ DOM

จำไว้ว่าคอนโซล JavaScript ของ Chrome เป็นสภาพแวดล้อมรันไทม์ JavaScript ที่ทำงานได้อย่างสมบูรณ์ ซึ่งหมายความว่าคุณไม่ จำกัด เพียงแค่ดูตัวแปร คุณสามารถเก็บเอาท์พุทko.contextForและจัดการ viewmodel ได้โดยตรงจากคอนโซล ลองvar root = ko.contextFor($0).$root; root.addContact();ดูว่าเกิดอะไรขึ้น :-)

การแก้ไขข้อบกพร่องมีความสุข!


7

ลองใช้สิ่งที่เรียบง่ายที่ฉันใช้:

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

หรือ

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

จากนั้นใน html ให้พูดว่าคุณมี:

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

เพียงแทนที่ด้วย

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

ขั้นสูงเพิ่มเติม:

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

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

สนุก :)

UPDATE

สิ่งที่น่ารำคาญอีกอย่างคือเมื่อคุณพยายามผูกค่าที่ไม่ได้กำหนด ลองนึกภาพในตัวอย่างด้านบนว่าวัตถุข้อมูลนั้นเป็นเพียง {} ไม่ใช่ {value: 'some text'} ในกรณีนี้คุณจะมีปัญหา แต่ด้วยการปรับแต่งต่อไปนี้คุณจะไม่เป็นไร:

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

5

ฉันสร้างโครงการ github ชื่อว่า knockthrough.js เพื่อช่วยให้เห็นภาพข้อผิดพลาดเหล่านี้

https://github.com/JonKragh/knockthrough

มันเน้นข้อผิดพลาดที่มีผลผูกพันและให้การถ่ายโอนของ datacontext บนโหนดนั้น

คุณสามารถเล่นกับตัวอย่างได้ที่นี่: http://htmlpreview.github.io/?https://github.com/JonKragh/knockthrough/blob/master/default.htm

ป้อนคำอธิบายรูปภาพที่นี่

ขอมอบเครดิตให้ RP Niemeyer สำหรับตัวอย่างรหัสพิศวงที่ยอดเยี่ยมของเขาใน SO เพื่อพาฉันไปที่จุดนี้


3

วิธีที่ง่ายที่สุดในการดูว่าข้อมูลใดที่ส่งผ่านไปยังการเชื่อมโยงคือการปล่อยข้อมูลไปยังคอนโซล:

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

สิ่งที่น่าพิศวงจะประเมินค่าสำหรับการโยงข้อความ ( การผูกใด ๆ สามารถใช้ที่นี่ในความเป็นจริง ) และล้างข้อมูล $ เพื่อคอนโซลแผงเบราว์เซอร์


2

คำตอบอื่น ๆ ทั้งหมดจะทำงานได้ดีฉันแค่เพิ่มสิ่งที่ฉันชอบ:

ในมุมมองของคุณ (สมมติว่าคุณได้ผูกไว้กับ ViewModel แล้ว):

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

รหัสที่น่าพิศวง:

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

การทำเช่นนี้จะเป็นการหยุดรหัสชั่วคราวในดีบักเกอร์elementและvalueAccessor()จะมีข้อมูลที่มีค่า


ไม่จำเป็นต้องมีการผูกแบบกำหนดเอง ดูstackoverflow.com/documentation/knockout.js/5066/…
Adam Wolski

1
ใช่ฉันเห็นด้วยว่าไม่จำเป็นต้องทำแบบนี้ฉันแค่อยากจะชี้ให้เห็นว่านี่เป็นรูปแบบการแก้ไขข้อบกพร่องหนึ่ง ... ทุกคนดูเหมือนจะชอบทำในแบบของตัวเอง :)
Aditya MP

1

หากคุณกำลังพัฒนาใน Visual Studio และ IE ฉันชอบสิ่งนี้มากกว่าdata-bind="somebinding:(function(){debugger; return bindvalue; })()"ฉันชอบฟังก์ชั่น echo มากกว่าเพราะมันจะไปที่สคริปต์ที่มีการผูกทั้งหมดแทนที่จะเป็นไฟล์ eval และคุณสามารถดู $ context $ data (ฉันใช้ สิ่งนี้ใน Chrome เช่นกัน);


ฉันเดิมพันว่าไม่มีอะไรเกี่ยวข้องกับ Visual Studio หรือ IE
Serhiy

@Serhiy Same with chrome แต่ใน chrome ฉันคิดว่าคุณสามารถเข้าถึงไฟล์ได้โดยไม่ต้องใช้มันฉันไม่คิดว่าคุณจะสามารถเข้าถึงไฟล์ใน VS ได้
Filip Cordas

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.