1

我无法绑定到由 afterRender 事件中的 AJAX 调用触发的 Knockout 模板创建的元素。正如您在此Fiddle中看到的,结果正确呈现,但在 afterRender 事件处理程序中,元素仍然不可用。

问题...

  • 由于 afterRender 事件处理程序运行时模板似乎没有呈现,因此模板如何正确呈现?

  • 为什么 AJAX 调用会影响结果?如果取消注释掉 AJAX 调用上方的行,则模板元素在 afterRender 事件中可用。

这是代码...

HTML

<div id="plugin" data-bind="template: { name: 'fooTemplate', data: $data, afterRender: postProcess }"></div>
<br />
<br />
<hr />
<div id="results"></div>

<script type="text/html" id="fooTemplate">
    <div data-bind="foreach: items()">
        <span data-bind="text: displayText"></span>
    </div>
</script>

JAVASCRIPT

var data = {
    items: [{
        displayText: 'Name',
    }, {
        displayText: 'Last Login Date',
    }, {
        displayText: 'Email',
    }]
};

function DataModel() {
    var self = this;
    self.items = ko.observableArray([]);
    self.data = ko.dependentObservable(function () {
        //self.items(data.items);//   <<== UNCOMMENT THIS LINE AND THE postProcess FUNCTION SHOWS FULLY RENDERED DOM
        $.ajax({
            url: '/some/path',
            error: function () {
                self.items(data.items);
            }
        });
    });

    postProcess = function () {
        $('#results').text($('#plugin').html());
    }
}

dataModel = new DataModel();
ko.applyBindings(dataModel);

一个注释...小提琴对虚假地址进行了 AJAX 调用。这样 Fiddle 就没有服务器依赖项了。错误属性用于更改导致模板运行的数据。但是,在我的开发环境中调用有效的 url 会产生与小提琴中显示的结果相同的结果。另外,我没有使用从服务器返回的数据来加载模板。而是小提琴在顶部使用静态定义的数据源(再次只是为了演示问题)。

4

1 回答 1

1

查看您的示例,您遇到了异步问题。

以下是在没有 $.ajax 调用的情况下流程的工作方式:

  1. dependentObservable 触发以更新值
  2. self.items 使用新值更新
  3. 模板呈现
  4. 调用 postProcess 方法,一切看起来都很好。

但是对于 $.ajax 调用,完成(和错误)方法是回调,因此流程会发生变化:

  1. dependentObservable(使用 ko.computed 代替!)触发更新值
  2. 对服务器进行 $.ajax 调用。
  3. 完成(或错误)回调在完成时排队等待。
  4. 模板呈现
  5. 调用了 postProcess 方法,但 self.items 仍然为空。
  6. 既然服务器响应并更新 self.items,done 回调就会触发
  7. 渲染的模板仍然绑定到您的视图模型,因此渲染的模板会更新。

我认为最简单的解决方法是将您的 ajax 调用从您的dependentObservable 中拉出,以允许您注释掉的情况。

于 2013-02-18T19:08:40.283 回答