knockout是否异步执行模型绑定?如果是这样,我该如何预防呢?

时间:2013-10-02 15:22:07

标签: javascript jquery knockout.js

在下面的代码中,我正在更新我的knockout模型属性SearchResults,然后我重新计算我的html中所有列的大小。我知道_resizeColumns函数可以正常工作。但是,在使用搜索结果更新DOM之前,它正在运行。我已经通过更新所有带黄色的div的背景颜色来验证是否正在调用_resizeColumns。在模型更新之前存在的div被设置为黄色,但搜索结果不是。

$.ajax({
    type: 'POST',
    url: 'foo.com',
    data: postData,
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    processData: true,
    success: function(data) {
      model.SearchResults(data.d); // updates the DOM with the search results via knockout.js
      _resizeColumns();            // does not resize the columns because they haven't been added to the DOM yet
    },
    error: function() { alert('error'); }
});

搜索结果会添加到DOM中,只是在我调用_resizeColumns

之后

更新 我不认为淘汰赛是异步运行的。我相信它是Web浏览器本身异步更新DOM。

更新2 直接从_resizeColumns()调用$(document).ready()函数。

更新3 我有两个版本_resizeColumns(),一个使用jquery选择器来获取和设置宽度,另一个在获取宽度时存储到二维数组中,并在设置时访问该二维数组。 2d阵列版本执行得更快。 2d阵列版本也导致我上面的原始问题中的问题。仅jquery版本没有。

2 个答案:

答案 0 :(得分:2)

在我的应用程序中,我遇到了类似的问题 - 我需要在Knockout呈现内容后设置列宽。我的解决方案是创建一个自定义绑定,我可以放在<table>元素上,每当表更新时都会更新(因为它绑定到同一个可观察数组)。当试图同步运行绑定时,我遇到了麻烦,但它很简单,让它以异步方式运行。这是我的约束力:

ko.bindingHandlers.fixColumnWidths = {
    update: function(element, valueAccessor) {
        if (ko.utils.unwrapObservable(valueAccessor())) {
            setTimeout(function() {
                $headings = $(element).find('thead th');
                if (!$headings.length) {
                    $headings = $(element.rows[0].cells);
                }
                $headings.width('').width(function(index, width) {
                    return width;
                });
            });
        }
    }
};

答案 1 :(得分:1)

你的问题的答案是否定的,Knockout不会异步执行绑定,除非你明确强制它。默认情况下,它会在转到下一个声明之前通知所有订阅者。

http://jsfiddle.net/uVgdF/

这可以这样看 -

self.updateSomethings = function () {
    self.somethings.push(new something('William', 1234432));
    alert('binding complete');
}