jQuery Knockout.js 完成渲染所有元素后的成功回调

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14254317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 13:23:44  来源:igfitidea点击:

success callback after knockout.js finishes rendering all the elements

jqueryforeachknockout.js

提问by rohitarora

I have implemented a knockout foreach binding, with multiple templates in the same page, one of the example is given here, what I am interested is in finding out when a block finishes rendering, I have tried afterRenderand afterAdd, but I guess it runs for each element, and not after the whole loop is finished.

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

<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>

I am interested in finding out just the success callback, when a loop finishes rendering.

当循环完成渲染时,我只想找出成功回调。

here is my afterAddfunction, which basically attaches some jQuery events, and nothing much.

这是我的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});
      });
  });
}

thanks in advance, and tell me there is a success callback :)

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

回答by Konstantin Dinev

You have the afterRendercallback in knockout.js:

你有afterRender回调knockout.js

foreach: { data: myItems, afterRender: renderedHandler }

Here's documentation.

这是文档。

Inside your handler check whether the length of the rendered collection is equal to the length of the items collection. If not don't execute the full rendered logic that you intend to use.

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

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

回答by Chuck Schneider

Try wrapping the ulwith

尝试ul

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

It will only work the first time everything within the template is rendered. But you will only get the one call to myPostProcessingLogic. Here's a fiddle

它只会在第一次呈现模板中的所有内容时起作用。但是您只会收到一次对 myPostProcessingLogic 的调用。这是一把小提琴

<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>

回答by Sohail xIN3N

Just wrap the foreach into another foreach loop using Knockout's container less method like this:

只需使用 Knockout 的 container less 方法将 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 -->

回答by Que Dee

Chuck Schneider's answer above is the best. I had to use containerless control as the foreach is on a tbody element:

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

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

回答by Malcolm Swaine

In version 3.5 Knockout provides events to notify when the contents of a node have been bound

在 3.5 版本中,Knockout 提供事件以在节点的内容已绑定时进行通知

HTML

HTML

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

JavaScript

JavaScript

function bindingComplete(){
...
}

If you an create event binding expression at a point in the DOM that encapsulates all your child data binding expression, then it's tantamount to a page binding complete event

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

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

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

回答by William Hammock

The solution above works great. Additionally, if you need to use the foreach "as" option you can do it as so:

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

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

回答by Zach Painter

I have just recently made a pull request with knockout for them to add two events to define in the binding, unwrap, then call in the correct spots before rendering the items and after all items have rendered. I haven't heard anything back from them but this does exactly what you want to do but you don't have to write hacky code to get it to work. I'm surprised that nobody has made this request before. I used these callbacks that I added to the source to destroy and reinitialize a knockout bound jquery datatable. This was the simplest solution. I have seen many attempts online that try and do it differently but this is the simplest solution.

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

Pull request: --> pr 1856

拉取请求:--> 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

淘汰赛数据表 JSFiddle

回答by Renon Stewart

Try afterRenderAllcallback in knockout.js:

afterRenderAll在knockout.js 中尝试回调:

foreach: { data: myItems, afterRenderAll: myPostProcessingLogic }

foreach: { 数据: myItems, afterRenderAll: myPostProcessingLogic }