【问题标题】:How to wait for entire template to render in KnockoutJS?如何等待整个模板在 KnockoutJS 中呈现?
【发布时间】:2012-07-17 13:06:01
【问题描述】:

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

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

【问题讨论】:

  • 也许你可以分享一个示例 afterRender 是在这种情况下使用的正确钩子。
  • 能否请您扩展您的评论,因为我不太清楚您的意思?抱歉在这里有点慢,辛苦了一天!
  • 只是想知道您是否可以共享您的代码,其中回调在非 foreach 场景中触发两次,所以我可以进一步帮助您。 afterRender 是您应该使用的正确钩子。这是一个示例:jsbin.com/umewov/edit#javascript,html,live
  • 我会尽快发布我的代码。我晚上要出去。
  • 好的,我有一个 B 计划,即将注入器配置设置编辑为 infuser.defaults.ajax.async = false

标签: templates knockout.js


【解决方案1】:

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

代替

options.afterRender = function() {

使用这个

self.options.afterRender = function() {

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

【讨论】:

    【解决方案2】:

    我也在学习使用外部模板(与您相同的库)进行淘汰赛,我的也被触发了两次。

    原因是在注入器渲染 loadingTemplate 时触发一次 afterRender,然后在加载实际外部模板时触发一次。所以即使我在我的配置中设置了选项:

    infuser.defaults.useLoadingTemplate = false;

    除了现在使用空模板外,它仍然会触发两次。这意味着我可以做到这一点(我的 afterRender 所做的只是在将模板加载到模态窗口并调整其大小后显示模态窗口)。

    为了避免双重事件触发而关闭异步可能并不理想。

    模板

    <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.
    
      }
    
    };
    

    如果有更好的方法或者我做错了什么,请告诉我:)

    【讨论】:

    • 感谢您提供的信息。下次我遇到模板问题时,我会考虑这一点。幸运的是,该项目目前已被搁置,但如果该项目恢复生机,我有你的建议。
    【解决方案3】:

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

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

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

    // 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 */});
    

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

    【讨论】:

      【解决方案4】:

      我设法不那么难看,快速修复了这个错误。看起来,在 externalTemplateEngine “加载” div 渲染之后,第一个“afterRender”回调被触发。所以快速修复是检查哪些元素已被渲染:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-28
        相关资源
        最近更新 更多