Tôi chỉ mới bắt đầu với Knockout.js (luôn muốn dùng thử, nhưng cuối cùng thì tôi cũng có cớ!) - Tuy nhiên, tôi đang gặp phải một số vấn đề hiệu suất thực sự tồi tệ khi liên kết một bảng với một tập hợp tương đối nhỏ dữ liệu (khoảng 400 hàng hoặc lâu hơn).
Trong mô hình của tôi, tôi có mã sau:
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!
}
};
Vấn đề là for
vòng lặp ở trên mất khoảng 30 giây hoặc lâu hơn với khoảng 400 hàng. Tuy nhiên, nếu tôi thay đổi mã thành:
this.loadData = function (data)
{
var testArray = []; //<-- Plain ol' Javascript array
for(var i = 0; i < data.length; i++)
{
testArray.push(new ResultRow(data[i]));
}
};
Sau đó, for
vòng lặp hoàn thành trong chớp mắt. Nói cách khác, push
phương thức của observableArray
đối tượng Knockout cực kỳ chậm.
Đây là mẫu của tôi:
<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>
Những câu hỏi của tôi:
- Đây có phải là cách phù hợp để liên kết dữ liệu của tôi (đến từ phương pháp AJAX) với một tập hợp có thể quan sát được không?
- Tôi mong đợi
push
là thực hiện một số re-calc nặng nề mỗi khi tôi gọi nó, chẳng hạn như có thể xây dựng lại các đối tượng DOM bị ràng buộc. Có cách nào để trì hoãn việc sửa lỗi này hoặc có thể đẩy tất cả các mặt hàng của tôi cùng một lúc?
Tôi có thể thêm nhiều mã nếu cần, nhưng tôi khá chắc rằng đây là những gì có liên quan. Đối với hầu hết các phần, tôi chỉ làm theo hướng dẫn Knockout từ trang web.
CẬP NHẬT:
Theo lời khuyên bên dưới, tôi đã cập nhật mã của mình:
this.loadData = function (data)
{
var mappedData = $.map(data, function (item) { return new ResultRow(item) });
this.projects(mappedData);
};
Tuy nhiên, this.projects()
vẫn mất khoảng 10 giây cho 400 hàng. Tôi thừa nhận rằng tôi không chắc điều này sẽ nhanh như thế nào nếu không có Knockout (chỉ thêm hàng thông qua DOM), nhưng tôi có cảm giác rằng nó sẽ nhanh hơn nhiều so với 10 giây.
CẬP NHẬT 2:
Theo lời khuyên khác bên dưới, tôi đã thử jQuery.tmpl (được hỗ trợ bởi KnockOut) và công cụ tạo khuôn mẫu này sẽ vẽ khoảng 400 hàng chỉ trong hơn 3 giây. Đây có vẻ là cách tiếp cận tốt nhất, ngắn gọn là một giải pháp có thể tải động nhiều dữ liệu hơn khi bạn cuộn.