【问题标题】:success callback after knockout.js finishes rendering all the elementsknockout.js 完成渲染所有元素后的成功回调
【发布时间】:2012-12-24 15:03:45
【问题描述】:

我已经实现了一个淘汰赛 foreach 绑定,在同一页面中有多个模板,这里给出了一个示例,我感兴趣的是找出一个块何时完成渲染,我尝试过 afterRender 和 @987654322 @,但我猜它会针对每个元素运行,而不是在整个循环完成后运行。

<ul data-bind="foreach: {data: Contacts, afterAdd: myPostProcessingLogic}">
  <li>
    <div class="list_container gray_bg mrgT3px">
      <div class="list_contact_icon"></div>
      <div class="contact_name"><span data-bind="text: first_name"></span> <span data-bind="text: last_name"></span></div>
      <div class="contact_number"><span data-bind="text: value"></span></div>
      <div class="callsms_container">
        <a href="#notification-box" class="notifcation-window">
          <div class="hover_btn tooltip_call">
            <div class="hover_call_icon"></div>
            <span>Call</span></div>
        </a>
        <a class="sendsms" href="#sendsms" rel="#sendsms">
          <div class="hover_btn tooltip_sms">
            <div class="hover_sms_icon"></div>
            <span>SMS</span></div>
        </a>
        <a href="#">
          <div class="hover_more_btn"></div>
        </a>
      </div>
      <!-- close callsms container -->
      <div id="notification-box" class="notification-popup">
        <a href="#" class="close"><img class="btn_close" src="images/box_cross.png" /></a> <img class="centeralign" src="images/notification_call.png" /> <span>Calling... +44 7401 287366</span> </div>
      <!-- close notification box -->
      <!-- close list gray bg -->
      <div class="tooltip_description" style="display:none" id="disp"> asdsadaasdsad </div>
    </div>
  </li>
</ul>

我有兴趣在循环完成渲染时找出成功回调。

这是我的afterAdd函数,它基本上附加了一些jQuery事件,并没有什么。

myPostProcessingLogic = function(elements) { 
  $(function(){
      $(".list_container_callog").hover(function(){  
          $(".callsms_container", this).stop().animate({left:"0px"},{queue:false,duration:800});
      }, function() {
          $(".callsms_container", this).stop().animate({left:"-98%"},{queue:false,duration:800});
      });
  });
}

提前谢谢,告诉我有一个成功回调:)

【问题讨论】:

    标签: jquery foreach knockout.js


    【解决方案1】:

    knockout.js 中有 afterRender 回调:

    foreach: { data: myItems, afterRender: renderedHandler }
    

    Here's documentation.

    在您的处理程序中检查渲染集合的长度是否等于项目集合的长度。如果不是,请不要执行您打算使用的完整呈现逻辑。

    renderedHandler: function (elements, data) {
        if ($('#containerId').children().length === this.myItems().length) {
            // Only now execute handler
        }
    }
    

    【讨论】:

    • 我已经用过了。问题是它在每个元素渲染后回调,而我有兴趣找出所有元素何时完成渲染
    • 是的,它是相同的,我有一个包含 10 个项目的数组,它的渲染 10 次。我遇到的问题是在每次渲染之后它执行 js,每个元素我只是希望它执行元素被显示出来。
    • @user1487459 我已经编写了更多示例代码。根据你所拥有的进行调整。
    • @user1487459 您正在获取对渲染元素的引用。您可以从那里检索父容器,而不是使用单个 ID。
    • 加上一个额外的内部 foreach 敲除似乎首先绑定了外部循环,这破坏了这种方法......有没有另一种方法来处理 foreach 及其内部的所有内容并在此之后执行一个函数?跨度>
    【解决方案2】:

    尝试用

    包裹ul
    <div data-bind='template: {afterRender: myPostProcessingLogic }'>
    

    它只会在模板中的所有内容第一次渲染时起作用。但是您只会接到对 myPostProcessingLogic 的一次调用。这是fiddle

    <div data-bind='template: {afterRender: myPostProcessingLogic }'>
      <ul data-bind="foreach: Contacts">
        <li>
          <div class="list_container gray_bg mrgT3px">
            <div class="list_contact_icon"></div>
            <div class="contact_name"><span data-bind="text: first_name"></span> <span data-bind="text: last_name"></span></div>
            <div class="contact_number"><span data-bind="text: value"></span></div>
            <div class="callsms_container">
              <a href="#notification-box" class="notifcation-window">
                <div class="hover_btn tooltip_call">
                  <div class="hover_call_icon"></div>
                  <span>Call</span></div>
              </a>
              <a class="sendsms" href="#sendsms" rel="#sendsms">
                <div class="hover_btn tooltip_sms">
                  <div class="hover_sms_icon"></div>
                  <span>SMS</span></div>
              </a>
              <a href="#">
                <div class="hover_more_btn"></div>
              </a>
            </div>
            <!-- close callsms container -->
            <div id="notification-box" class="notification-popup">
              <a href="#" class="close"><img class="btn_close" src="images/box_cross.png" /></a> <img class="centeralign" src="images/notification_call.png" /> <span>Calling... +44 7401 287366</span> </div>
            <!-- close notification box -->
            <!-- close list gray bg -->
            <div class="tooltip_description" style="display:none" id="disp"> asdsadaasdsad </div>
          </div>
        </li>
      </ul>
    </div>
    

    【讨论】:

    • 对我不起作用。该函数在内容完全呈现之前被调用。
    • 这种方法与 Slick 轮播库结合使用对我很有效。
    【解决方案3】:

    Chuck Schneider 上面的回答是最好的。 我不得不使用无容器控件,因为 foreach 位于 tbody 元素上:

    <!-- ko template: {afterRender: SetupCheckboxes } -->
    <tbody data-bind="foreach: selectedItems" id="gridBody">
      <tr>
        <td>
          <input type="checkbox" />
        </td>
      </tr>
    </tbody>
    <!-- /ko -->
    

    【讨论】:

      【解决方案4】:

      使用 Knockout 的无容器方法将 foreach 包装到另一个 foreach 循环中,如下所示:

      <!-- ko foreach:{data: Contacts, afterRender: myPostProcessingLogic }-->
      <ul data-bind="foreach: $data}">
        <li>
          <div class="list_container gray_bg mrgT3px">
            <div class="list_contact_icon"></div>
            <div class="contact_name"><span data-bind="text: first_name"></span> <span data-bind="text: last_name"></span></div>
            <div class="contact_number"><span data-bind="text: value"></span></div>
            <div class="callsms_container">
              <a href="#notification-box" class="notifcation-window">
                <div class="hover_btn tooltip_call">
                  <div class="hover_call_icon"></div>
                  <span>Call</span></div>
              </a>
              <a class="sendsms" href="#sendsms" rel="#sendsms">
                <div class="hover_btn tooltip_sms">
                  <div class="hover_sms_icon"></div>
                  <span>SMS</span></div>
              </a>
              <a href="#">
                <div class="hover_more_btn"></div>
              </a>
            </div>
            <!-- close callsms container -->
            <div id="notification-box" class="notification-popup">
              <a href="#" class="close"><img class="btn_close" src="images/box_cross.png" /></a> <img class="centeralign" src="images/notification_call.png" /> <span>Calling... +44 7401 287366</span> </div>
            <!-- close notification box -->
            <!-- close list gray bg -->
            <div class="tooltip_description" style="display:none" id="disp"> asdsadaasdsad </div>
          </div>
        </li>
      </ul>
      <!-- /ko -->
      

      【讨论】:

        【解决方案5】:

        上面的解决方案效果很好。此外,如果您需要使用 foreach "as" 选项,您可以这样做:

        data-bind="foreach: { data: myItems, afterRender: renderedHandlet, as: 'myItem'}">
        

        【讨论】:

          【解决方案6】:

          在 3.5 版中,Knockout 提供事件来通知节点的内容何时被绑定

          HTML

          <div data-bind="childrenComplete: bindingComplete">...</div>
          

          JavaScript

          function bindingComplete(){
          ...
          }
          

          如果您在 DOM 中封装所有子数据绑定表达式的某个点创建事件绑定表达式,那么它就相当于页面绑定完成事件

          参考 https://knockoutjs.com/documentation/binding-lifecycle-events.html

          【讨论】:

            【解决方案7】:

            我最近刚刚提出了一个带有淘汰赛的拉取请求,要求他们添加两个事件以在绑定中定义,展开,然后在渲染项目之前和所有项目渲染之后调用正确的位置。我没有收到他们的任何回复,但这正是您想要做的,但您不必编写 hacky 代码来让它工作。我很惊讶以前没有人提出过这个要求。我使用添加到源中的这些回调来销毁和重新初始化淘汰赛绑定的 jquery 数据表。这是最简单的解决方案。我在网上看到很多尝试不同的方法,但这是最简单的解决方案。

            拉取请求:--> pr 1856

            ko.bindingHandlers.DataTablesForEach = {
            
              init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
                var nodes = Array.prototype.slice.call(element.childNodes, 0);
                ko.utils.arrayForEach(nodes, function(node) {
                  if (node && node.nodeType !== 1) {
                    node.parentNode.removeChild(node);
                  }
                });
                return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
              },
              update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            
                var value = ko.unwrap(valueAccessor()),
                  key = "DataTablesForEach_Initialized";
            
                var newValue = function() {
                  return {
                    data: value.data || value,
                    beforeRenderAll: function(el, index, data) {
            
                      if (ko.utils.domData.get(element, key)) {
            
                        $(element).closest('table').DataTable().destroy();
                      }
                    },
                    afterRenderAll: function(el, index, data) {
                      $(element).closest('table').DataTable(value.options);
                    }
                  };
                };
            
                ko.bindingHandlers.foreach.update(element, newValue, allBindingsAccessor, viewModel, bindingContext);
            
                //if we have not previously marked this as initialized and there is currently items in the array, then cache on the element that it has been initialized
                if (!ko.utils.domData.get(element, key) && (value.data || value.length)) {
                  ko.utils.domData.set(element, key, true);
                }
            
                return {
                  controlsDescendantBindings: true
                };
              }
            };
            

            Knockout Datatables JSFiddle

            【讨论】:

              【解决方案8】:

              在 knockout.js 中尝试afterRenderAll 回调:

              foreach: { data: myItems, afterRenderAll: myPostProcessingLogic }

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-07-07
                • 2022-08-05
                • 2013-01-10
                • 2013-12-26
                • 1970-01-01
                • 1970-01-01
                • 2013-09-29
                相关资源
                最近更新 更多