javascript - Knockout - 绑定(bind)到引用对象

标签 javascript jquery performance knockout.js

我有一个 knockout 应用程序,其中“估算”是页面的主要对象。该估计包含 WorkOrder 对象 (WorkOrdersDTO) 的 observableArray,但一次仅显示一个 WorkOrder 对象以供编辑。用户可以通过从选择列表中进行选择来选择显示哪个工作订单以进行编辑。我遇到的问题是我正在使用名为 CurrentWorkOrder 的对象来引用当前正在编辑的 WorkOrder。设置此对象时,我遇到了一些性能问题。估计包含的工作订单越多,这些性能问题就越严重。当用户添加工作订单时会出现最大的问题。这是该过程的代码:

self.addWorkOrder = function () {
    tempWOId += 1;
    var workOrder = new WorkOrder();
    workOrder.WorkOrderId(tempWOId);
    workOrder.WorkOrderNo(self.SetWorkOrderNo());
    self.estimate().WorkOrdersDTO.push(workOrder);
    self.estimate().CurrentWorkOrder($.grep(self.estimate().WorkOrdersDTO(), function (wo) { return wo == workOrder })[0]);
};

该函数的最后一行是花费最多时间的一行。我也尝试过使用这个,但它甚至更慢。

self.estimate().CurrentWorkOrder(self.estimate().WorkOrdersDTO()[self.estimate().WorkOrdersDTO().length - 1]);

我还删除了 html 中的“with”绑定(bind),但没有看到任何结果。我什至注释掉了发生绑定(bind)的整个 html,以确保性能问题不是由此引起的,并且性能没有变化。

有什么想法吗?

我返回并用几种不同的方式对该行代码进行计时,结果如下: 当前工作订单($.grep) - 613.000ms

当前工作订单(WorkOrdersDTO.length) - 740.000ms

当前工作订单(工作订单) - 689.000 毫秒

CurrentWorkOrder($.grep) 没有 html 引用 - 317.000ms

当绑定(bind)到 CurrentWorkOrder 的 HTML 被删除时,性能会好得多,这让我相信这就是问题所在。这是该部分的完整 HTML:

<div id="work-order-details">
        <div class="work-order-details" data-bind='with: estimate' style="margin-bottom:5px;">
            <table style="width:100%">
                <tr>
                    <td>
                        <table>
                            <tr>
                                <td style="text-align:right;">
                                    Group
                                </td>
                                <td>
                                    <select class="k-input" data-bind='options: WorkOrderGroupsDTO, value: CurrentWorkOrder().WorkOrderGroupId, optionsValue: "WorkOrderGroupId", optionsText: "GroupName", optionsCaption: "--Select--"'></select>
                                </td>
                                <td>
                                    <span id="AddWorkOrderGroupButton"><span class="icon-add" data-bind='click: $root.addWorkOrderGroup'></span>
                                </td>
                                <td>
                                    Service Date
                                </td>
                                <td>
                                    <input style="width:120px;" id='service-date' data-bind="value: CurrentWorkOrder().ServiceDateDisplay" />
                                </td>
                            </tr>
                        </table>
                    </td>
                    <td style="text-align:right;">
                        Additional Work Orders&nbsp;<select id='workOrderSelect' class="k-input num-textbox" data-bind="options: WorkOrdersDTO, optionsValue: 'WorkOrderId', optionsText: 'WorkOrderNo'"></select>
                    </td>
                </tr>
            </table>
        </div>
        <div class="work-order-details" data-bind='with: estimate'>
            <table class="table-container" style="border:solid 1px darkgray;">
                <tr>
                    <th class="table-cell-2 estimate-wo-header" colspan="2">INSTRUCTIONS</th>
                </tr>
                <tr class="table-row">
                    <td colspan='2'>
                        <textarea class="textarea" name="" id="estimate-textarea" rows="4" data-bind='value: CurrentWorkOrder().Instructions' placeholder='Enter Instructions...'></textarea>
                    </td>
                </tr>
                <tr>
                    <th class="table-cell-2 estimate-wo-header labor-tasks">LABOR INFORMATION 
                        <a href="#" data-bind='click: $root.addWorkOrderLaborTask'>Add</a>
                    </th>
                    <th class="table-cell-2 estimate-wo-header packing-materials">PACKING MATERIALS<a href="#" data-bind='click: $root.addWorkOrderPackingMaterial'>Add</a></th>
                </tr>
                <tr class="table-row">
                    <td class="table-cell-3 labor-tasks" style="border:solid 1px darkgray;padding-left:10px;padding-bottom:10px;">
                        <table class="estimate-table">
                            <tr class="header-row">
                                <td>Task</td>
                                <td>Qty</td>
                                <td>Hours</td>
                                <td>RT Rate</td>
                                <td>OT Rate</td>
                                <td>PT Rate</td>
                                <td>Cost</td>
                            </tr>
                            <tbody class='table-body' data-bind="foreach: CurrentWorkOrder().WorkOrderLaborTasksDTO">
                                <tr>
                                    <td>
                                        <select class="k-input smaller-textbox" data-bind='options: LaborTaskData, value: LaborTaskId, optionsValue: "LaborTaskId", optionsText: "Task", optionsCaption: "--Select--"'/>
                                    </td>
                                    <td>
                                        <input type="number" min='0' class="k-textbox num-textbox" style="width:40px;" data-bind='value: Quantity' onkeypress="return numeric_only(event)" />
                                    </td>
                                    <td>
                                        <input type="number" min='0' class="k-textbox num-textbox" data-bind='value: TotalHours' onkeypress="return numeric_only(event)" />
                                    </td>
                                    <td>
                                        $0.00
                                    </td>
                                    <td>
                                        $0.00
                                    </td>
                                    <td>
                                        $0.00
                                    </td>
                                    <td>
                                        <span data-bind='text: TotalCostDisplay'></span>
                                    </td>
                                    <td>
                                        <a href='#' data-bind='click: $root.removeWorkOrderLaborTask'>X</a>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td class="table-cell-2 packing-materials" style="border:solid 1px darkgray;padding-left:10px;padding-bottom:10px;">
                        <table class="estimate-table">
                            <tr class="header-row">
                                <td>Material</td>
                                <td>Qty</td>
                                <td>Unit Price</td>
                                <td>Cost</td>
                                <td></td>
                            </tr>
                            <tbody class='table-body' data-bind="foreach: CurrentWorkOrder().WorkOrderPackingMaterialsDTO">
                                <tr>
                                    <td><select style="width:275px;" class="k-input" data-bind="options: PackingMaterialData, value: MaterialId, optionsValue: 'MaterialId', optionsText: 'Description', optionsCaption: '--Select--'"></select></td>
                                    <td><input type="number" min='0' class="k-textbox num-textbox" data-bind='value: Quantity' onkeypress="return numeric_only(event)" /></td>
                                    <td><span data-bind='text: UnitPrice'></span></td>
                                    <td><span data-bind='text: CostDisplay'></span></td>
                                    <td><a href='#' data-bind='click: $root.removeWorkOrderPackingMaterial'>X</a></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
                <tr>
                    <th class="table-cell-2 estimate-wo-header installation-products">INSTALLATION <a id='add-installation-product' href="#" data-bind="click: $root.addWorkOrderInstallationProduct">Add</a></th>
                    <th class="table-cell-2 estimate-wo-header unitized-items">UNITIZED PRICING <a id='add-installation-product' href="#" data-bind="click: $root.addWorkOrderUnitizedItem">Add</a></th>
                </tr>
                <tr class="table-row">
                    <td class="table-cell-2 installation-products" style="border:solid 1px darkgray;padding-left:10px;padding-bottom:10px;">
                        <table class="estimate-table">
                            <tr class="header-row">
                                <td>Manufacturer</td>
                                <td>Product Line</td>
                                <td>Cost</td>
                                <td></td>
                            </tr>
                            <tbody class='table-body' data-bind="foreach: CurrentWorkOrder().WorkOrderInstallationProductsDTO">
                                <tr>
                                    <td hidden data-bind='text: WorkOrderInstallationProductId'></td>
                                    <td>
                                        <select class="k-input larger-textbox select-mfr" data-bind="options: ManufacturerData, value: ManufacturerId, optionsValue: 'ManufacturerId', optionsText: 'Name', optionsCaption: '--Select--'"></select>
                                    </td>
                                    <td>
                                        <select data-bind="options: ProductLines, value: ProductId, optionsValue: 'ProductLineId', optionsText: 'Name', optionsCaption: '--Select--'" id="" class="k-input big-textbox"></select>
                                    </td>
                                    <td data-bind="text: CostDisplay"></td>
                                    <td>
                                        <a href='#' data-bind='click: $root.editWorkOrderInstallationProduct'>Edit</a>
                                        <a href='#' data-bind='click: $root.removeWorkOrderInstallationProduct'>X</a>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td class="table-cell-2 unitized-items" style="border:solid 1px darkgray;padding-left:10px;padding-bottom:10px;">
                        <table class="estimate-table">
                            <tr class="header-row">
                                <td>Service</td>
                                <td>Qty</td>
                                <td>Unit Price</td>
                                <td>Cost</td>
                                <td></td>
                            </tr>
                            <tbody class='table-body' data-bind="foreach: CurrentWorkOrder().WorkOrderUnitizedItemsDTO">
                                <tr>
                                    <td><select style="width:275px;" class="k-input" data-bind="options: UnitizedItemData, value: UnitId, optionsValue: 'UnitId', optionsText: 'Description', optionsCaption: '--Select--'"></select></td>
                                    <td><input type="number" min='0' class="k-textbox num-textbox" data-bind='value: Quantity' style="width:40px;" onkeypress="return numeric_only(event)" /></td>
                                    <td><span data-bind='text: UnitPrice'></span></td>
                                    <td><span data-bind='text: CostDisplay'></span></td>
                                    <td><a href='#' data-bind='click: $root.removeWorkOrderUnitizedItem'>X</a></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
                <tr>
                    <th class="table-cell-2 estimate-wo-header storage">STORAGE & HANDLING <a id='add-storage' href="#" data-bind="click: $root.addWorkOrderStorage">Add</a></th>
                    <th class="table-cell-2 estimate-wo-header tech-services">TECH SERVICES<a href="#" data-bind='click: $root.addWorkOrderTechService'>Add</a></th>                    
                </tr>
                <tr class="table-row">
                    <td class="table-cell-2 storage" style="border:solid 1px darkgray;padding-left:10px;padding-bottom:10px;">
                        <table class="estimate-table">
                            <tr class="header-row">
                                <td>Inventory</td>
                                <td>Storage</td>
                                <td>Handling</td>
                                <td>Valuation</td>
                                <td>Cost</td>
                            </tr>
                            <tbody class='table-body' data-bind="foreach: CurrentWorkOrder().WorkOrderStoragesDTO">
                                <tr>
                                    <td class="storage-cell"><span data-bind="text: InventoryTypeName"></span></td>
                                    <td class="storage-cell"><span data-bind="text: EstimatedStorage"></span></td>
                                    <td class="storage-cell"><span data-bind="text: HandlingIn"></span></td>
                                    <td class="storage-cell"><span data-bind='text: ValuationTypeCharges'></span></td>
                                    <td class="storage-cell"><span data-bind='text: EstimatedStorage'></span></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td class="table-cell-2 tech-services" style="border:solid 1px darkgray;padding-left:10px;padding-bottom:10px;">
                    <table class="estimate-table">
                            <tr class="header-row">
                                <td>Service</td>
                                <td>Qty</td>
                                <td>Unit Price</td>
                                <td>Cost</td>
                                <td></td>
                            </tr>
                            <tbody class='table-body' data-bind="foreach: CurrentWorkOrder().WorkOrderTechServicesDTO">
                                <tr>
                                    <td><select style="width:275px;" class="k-input" data-bind="options: TechServiceData, value: UnitId, optionsValue: 'UnitId', optionsText: 'Description', optionsCaption: '--Select--'"></select></td>
                                    <td><input type="number" min='0' class="k-textbox num-textbox" data-bind='value: Quantity' onkeypress="return numeric_only(event)" /></td>
                                    <td><span data-bind='text: UnitPrice'></span></td>
                                    <td><span data-bind='text: CostDisplay'></span></td>
                                    <td><a href='#' data-bind='click: $root.removeWorkOrderTechService'>X</a></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
                <tr>
                    <th class="table-cell-2 estimate-wo-header other-services">OTHER SERVICES <a id='add-other-service' href="#" data-bind='click: $root.addWorkOrderOtherService'>Add</a></th>
                    <th class="table-cell-2 estimate-wo-header third-party-services">THIRD PARTY SERVICES <a id='add-third-service' href="#" data-bind='click: $root.addWorkOrderThirdPartyService'>Add</a></th>
                </tr>
                <tr class='table-row'>
                    <td class="table-cell-2 other-services" style="border:solid 1px darkgray;padding-left:10px;padding-bottom:10px;">
                        <table class='estimate-table'>
                            <tr class="header-row">
                                <td>Description</td>
                                <td>Cost</td>
                            </tr>
                            <tbody class='table-body' data-bind="foreach: CurrentWorkOrder().WorkOrderOtherServicesDTO">
                                <tr>
                                    <td><input style="width:360px;" class="k-textbox" type="text" data-bind="value: Description" /></td>
                                    <td><input class="k-textbox smaller-textbox" data-bind='value: CostDisplay' onkeypress="return numeric_only(event)" /></td>
                                    <td><a href='#' data-bind='click: $root.removeWorkOrderOtherService'>X</a></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                    <td class="table-cell-2 third-party-services" style="border:solid 1px darkgray;padding-left:10px;padding-bottom:10px;">
                        <table class='estimate-table'>
                            <tr class="header-row">
                                <td>Description</td>
                                <td>Source</td>
                                <td>Src Cost</td>
                                <td>Cost</td>
                            </tr>
                            <tbody class='table-body' data-bind="foreach: CurrentWorkOrder().WorkOrderThirdPartyServicesDTO">
                                <tr>
                                    <td><input class="k-textbox" type="text" data-bind="value: Description" /></td>
                                    <td><input class="k-textbox smaller-textbox" type="text" data-bind="value: Source" /></td>
                                    <td><input class="k-textbox mini-textbox" type="text" data-bind="value: SourceCost" /></td>
                                    <td><input class="k-textbox mini-textbox" data-bind='value: CostDisplay' style="width:40px;" /></td>
                                    <td><a href='#' data-bind='click: $root.removeWorkOrderThirdPartyService'>X</a></td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
            </table>
        </div>

我认为不使用表格可以使标记渲染速度更快,但我一直犹豫是否要切换它,因为这是其他开发人员更喜欢的。

最佳答案

你的最后一行实际上只是一种复杂且耗时的做法

self.estimate().CurrentWorkOrder(workOrder);

由于 workOrder 是使用构造函数实例化的,因此它将是数据中唯一可以与自身进行比较的对象,因此无需搜索它。

关于javascript - Knockout - 绑定(bind)到引用对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21537948/

相关文章:

performance - 现代CPU每滴答的缓存带宽

javascript - 是否有依赖于 chrome 而不是 safari 的 pywebview 替代品

javascript - HTML <body> fadeIn/fadeOut 与 jQuery 仅适用于显示 :none

java - Java序列化是缩小内存占用的工具吗?

jquery - 在文本中查找链接并使用 jquery 将其包装在标签中

javascript - 当弹出窗口关闭时触发页面上的事件

mysql - 左连接或条件执行缓慢

javascript - 这个数组排序功能实际上是如何工作的?

javascript - 在 Chrome 开发者工具中调试时分割 JavaScript 长度的任何方法

javascript - 内容更改时 div 大小的动画变化