Knockout:对可观察数组进行推送,使每个项目的计算可观察性被执行



在下面的代码中,我向可观察数组添加了一个项。这导致所有以前的项目在执行.push时执行其计算的可观察项。这是不必要的。如何防止这种情况发生?我拥有的项目越多,这意味着计算出的每个可观察项目都将运行。

参见小提琴示例。http://jsfiddle.net/k8kbdnnv/3/

html代码

    <div id="logs"></div>
<table>  
<tbody data-bind="foreach: CompanySearchRows">
                <tr >
                    <td>
                        <input data-bind='textInput: ClientReference' type="text"  />
                    </td>
                    <td>
                        <input data-bind='textInput: CompanySearchReference' type="text"  />
                    </td>
                </tr>
            </tbody>
</table>

jscode

var viewModel;
var maxTitleRefRows = 50;
function ViewModel() {
    var self = this;
    self.CompanySearchRows = new ko.observableArray([new ItemViewModel()]);
    self.Executions = ko.observable(0);
    self.addRow = function (clientReference) {  

    var newRow = new ItemViewModel();       
    self.CompanySearchRows.push(newRow);  //this causes the code to jump 
into each array item's OnCompanySearchReferenceChanged computed observable 
    };
}

function ItemViewModel() {
    var self = this;   
    self.ClientReference = ko.observable(""); 
    self.CompanySearchReference = ko.observable(""); 
self.OnCompanySearchReferenceChanged = ko.computed(function () {               
    var reference = self.CompanySearchReference();
   logIt("computed executed" + reference);

    if (reference !== ""  ) {                    
        var currentIndex = viewModel.CompanySearchRows.indexOf(self);
        viewModel.Executions(currentIndex);
        var length = viewModel.CompanySearchRows().length;
        var lastItemIndex = length - 1;   
        if (currentIndex === lastItemIndex && length < maxTitleRefRows ) {          
            viewModel.addRow(self.ClientReference());               
        }
    }
    return;
});      
}
var logs=document.getElementById('logs');
function logIt(msg){
    var e=document.createElement('div');
    e.innerHTML=msg;
    logs.insertBefore(e,logs.firstChild);
}
$(document).ready(function () {
    viewModel = new ViewModel();
    ko.applyBindings(viewModel);    
});

computed函数包含对主ViewModel中observableArray的引用。这意味着,如果数组发生变化(例如,从push,则会重新评估所有项的计算函数。

读取代码时,计算函数的意图似乎是在第二个字段中输入值时添加新行。因此,我们只需要跟踪最后一个项目即可完成此操作。通常建议不要在子对象内部这样做-主视图模型应该管理数组,子对象应该独立于它

为了实现这一点,我在CompanySearchReference observable上使用了订阅,但仅在最后一项上使用。当该值更改时,父ViewModel将添加新行,并删除前一行上的订阅,因此在任何时候都只有一个订阅处于活动状态。

// subscribe to changes on the child's search reference
// when this has a value, create a new row
var subscription = newRow.CompanySearchReference.subscribe(function (newValue) {
   if (newValue && self.CompanySearchRows().length < maxTitleRefRows) {
       // value has been changed: first remove this subscription
       logIt("removing subscription");
       subscription.dispose();
       // add a new row (creates a new subscription on new row)
       logIt("adding new row");
       self.addRow();
   }
});

完整的JSFiddle位于http://jsfiddle.net/Quango/fgfw6Ld0/

最新更新