如何在KnockoutJS中等待整个模板渲染?

时间:2012-07-17 13:06:02

标签: templates knockout.js

当整个模板完成渲染时,KnockoutJS中有没有办法让回调发生?

我了解您可以使用afterRender选项:

"template: { name: 'Template', afterRender : myCallback}"

但回调在我的测试页面中触发两次(我没有使用foreach,也没有要显示的数据集合。)

我看到以下问题与我提出的问题类似:

KnockoutJS bind event after template render

但那个问题的答案并没有帮助我。

Knockout中是否有一个事件在整个模板完成渲染后触发,而不是在KO找到的每个元素之后触发?

编辑: 该死的,我急着发布这个问题,我忘了提到我用它来加载模板:

https://github.com/ifandelse/Knockout.js-External-Template-Engine

由于模板存储在外部文件中。

4 个答案:

答案 0 :(得分:1)

我无法(快速)在github上找到进一步解释这一条目的条目,但afaik它呈现两次的原因是一个错误。我的外部模板引擎的本地副本在第22行有一个额外的“self”,它修复了它。

而不是

options.afterRender = function() {

使用此

self.options.afterRender = function() {

请注意,NuGet中的版本似乎已经过时,GitHub版本已经包含此修复程序。

答案 1 :(得分:0)

我也在学习基于外部模板的淘汰赛(和你一样的库),我的也是两次射击。

原因是当infuser呈现loadingTemplate时afterRender触发一次,然后在加载实际外部模板时触发一次。所以即使我在配置中设置了选项:

infuser.defaults.useLoadingTemplate = false;

除了现在有一个空模板,它仍然会触发两次。这意味着我可以做到这一点(我的所有afterRender都会在模板加载到模板窗口后显示模态窗口,并调整大小到内容)。

关闭异步以解决双重事件发射可能并不理想。

TEMPLATE

<div data-bind="template: { name: template().name(), data: template().data(), afterRender: renderComplete }"></div>

查看模型

var renderComplete = function (params) {

  if (params.length > 0) {

     //Do my stuff here.

  }

};

如果有更好的方法或我做了明显错误的事情,请告诉我:)

答案 2 :(得分:0)

我正在为KO使用不同的AMD库,作者写的一个。

https://github.com/rniemeyer/knockout-amd-helpers

我不是最优雅的解决方案,但它确实有效。我所做的是使用setTimeout(回调,100)为我的所有模板添加一个afterRender调用。回调设置了一个延迟解析的jQuery。当延迟解决后,我知道我的所有渲染都已完成,并且可以执行我的代码。

// create a jQuery deferred
var dfd = $.Deferred();

// in my template call
afterRender: function () {

  // clear the timeout if it's still in play
  if (renderTimeoutId !== undefined) {
      clearTimeout(renderTimeoutId);
  }

  // create a new timeout and restart the clock
  renderTimeoutId = setTimeout(function () {
      dfd.resolve();
  }, 100);
}

// when my code is complete
dfd.done(function(){ /* after rendering code */});

我对这个更优雅的解决方案非常感兴趣,我真的不喜欢我的代码依赖于超时,但这是我当时能想到的最好的。

答案 3 :(得分:0)

我设法做了不那么难看,快速修复这个bug。看来,在渲染externalTemplateEngine“loading”div之后,第一个“afterRender”回调被触发了。所以快速解决方法是检查已呈现的元素:

afterRender = function (params) {
    // console.log(params);
    if (params.length <= 0 || $(params[0]).hasClass('infuser-loading'))
        return;

    // ... your code goes here
}