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
success callback after knockout.js finishes rendering all the elements
提问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 afterRender
and afterAdd
, but I guess it runs for each element, and not after the whole loop is finished.
我已经实现了一个淘汰赛 foreach 绑定,在同一页面中有多个模板,这里给出了一个例子,我感兴趣的是找出一个块何时完成渲染,我已经尝试过afterRender
和afterAdd
,但我猜它为每个运行元素,而不是在整个循环完成之后。
<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 afterAdd
function, 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 afterRender
callback in knockout.js
:
你有afterRender
回调knockout.js
:
foreach: { data: myItems, afterRender: renderedHandler }
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 ul
with
尝试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
};
}
};
回答by Renon Stewart
Try afterRenderAll
callback in knockout.js:
afterRenderAll
在knockout.js 中尝试回调:
foreach: { data: myItems, afterRenderAll: myPostProcessingLogic }
foreach: { 数据: myItems, afterRenderAll: myPostProcessingLogic }