ฉันเพิ่งเริ่มใช้ Knockout.js (อยากลองใช้เสมอ แต่ตอนนี้ฉันมีข้อแก้ตัว!) - อย่างไรก็ตามฉันพบปัญหาประสิทธิภาพการทำงานที่แย่มากเมื่อผูกตารางกับชุดที่ค่อนข้างเล็ก ข้อมูล (ประมาณ 400 แถวหรือมากกว่านั้น)
ในรุ่นของฉันฉันมีรหัสต่อไปนี้:
this.projects = ko.observableArray( [] ); //Bind to empty array at startup
this.loadData = function (data) //Called when AJAX method returns
{
for(var i = 0; i < data.length; i++)
{
this.projects.push(new ResultRow(data[i])); //<-- Bottleneck!
}
};
ปัญหาคือการfor
วนรอบด้านบนใช้เวลาประมาณ 30 วินาทีหรือประมาณนั้นโดยมีประมาณ 400 แถว อย่างไรก็ตามหากฉันเปลี่ยนรหัสเป็น:
this.loadData = function (data)
{
var testArray = []; //<-- Plain ol' Javascript array
for(var i = 0; i < data.length; i++)
{
testArray.push(new ResultRow(data[i]));
}
};
จากนั้นการfor
วนซ้ำจะเสร็จสิ้นในพริบตา กล่าวอีกนัยหนึ่งpush
วิธีการของobservableArray
วัตถุของ Knockout นั้นช้าอย่างไม่น่าเชื่อ
นี่คือแม่แบบของฉัน:
<tbody data-bind="foreach: projects">
<tr>
<td data-bind="text: code"></td>
<td><a data-bind="projlink: key, text: projname"></td>
<td data-bind="text: request"></td>
<td data-bind="text: stage"></td>
<td data-bind="text: type"></td>
<td data-bind="text: launch"></td>
<td><a data-bind="mailto: ownerEmail, text: owner"></a></td>
</tr>
</tbody>
คำถามของฉัน:
- นี่เป็นวิธีที่ถูกต้องในการผูกข้อมูลของฉัน (ซึ่งมาจากเมธอด AJAX) กับคอลเล็กชันที่สังเกตได้หรือไม่
- ฉันคาดว่า
push
จะทำการคำนวณซ้ำอย่างหนักทุกครั้งที่ฉันเรียกมันเช่นอาจจะสร้างวัตถุ DOM ที่ถูกผูกไว้ใหม่ มีวิธีใดที่จะชะลอการคำนวณใหม่นี้หรืออาจผลักดันรายการทั้งหมดของฉันในคราวเดียว?
ฉันสามารถเพิ่มรหัสเพิ่มเติมได้หากจำเป็น แต่ฉันค่อนข้างมั่นใจว่านี่คือสิ่งที่เกี่ยวข้อง ส่วนใหญ่ฉันแค่ทำตามแบบฝึกหัด Knockout จากเว็บไซต์
อัพเดท:
ตามคำแนะนำด้านล่างฉันได้อัปเดตรหัสของฉันแล้ว:
this.loadData = function (data)
{
var mappedData = $.map(data, function (item) { return new ResultRow(item) });
this.projects(mappedData);
};
อย่างไรก็ตามthis.projects()
ยังคงใช้เวลาประมาณ 10 วินาทีสำหรับ 400 แถว ฉันยอมรับว่าฉันไม่แน่ใจว่าสิ่งนี้จะเร็วแค่ไหนหากไม่มีสิ่งที่น่าพิศวง (เพียงแค่เพิ่มแถวผ่าน DOM) แต่ฉันรู้สึกว่ามันจะเร็วกว่า 10 วินาทีมาก
อัปเดต 2:
ตามคำแนะนำอื่น ๆ ด้านล่างฉันให้jQuery.tmplยิง (ซึ่ง KnockOut สนับสนุน) และเครื่องมือสร้างเทมเพลตนี้จะวาดประมาณ 400 แถวในเวลาเพียง 3 วินาที นี่ดูเหมือนจะเป็นแนวทางที่ดีที่สุดซึ่งไม่ใช่วิธีแก้ปัญหาที่จะโหลดข้อมูลเพิ่มเติมแบบไดนามิกเมื่อคุณเลื่อน