如何在jQuery .append
完成后调用函数?
以下是一个例子:
$("#root").append(child, function(){
// Action after append is completly done
});
问题:当附加复杂的DOM结构时,在追加函数回调中计算根元素的新大小是错误的。假设DOM仍然没有完全加载,只有添加的复杂DOM的第一个孩子是。
答案 0 :(得分:65)
你在这里有很多有效的答案,但没有一个真正告诉你为什么它的工作原理。
在JavaScript命令中,按照它们的顺序同步执行一个命令,除非您通过使用超时或间隔明确告诉它们是异步的。
这意味着您的.append
方法将被执行,并且在该方法完成其工作之前,不执行任何其他操作(忽略可能存在的任何可能的超时或间隔)。
总结一下,由于.append
将同步运行,因此无需回调。
答案 1 :(得分:17)
嗯,我有完全相同的尺寸重新计算问题,经过数小时的头痛后,我不得不反对.append()
表现严格同步。好吧,至少在Google Chrome中。请参阅以下代码。
var input = $( '<input />' );
input.append( arbitraryElement );
input.css( 'padding-left' );
在Firefox中正确检索了padding-left属性,但在Chrome中它是空的。像我想的所有其他CSS属性一样。经过一些实验后,我不得不安排将CSS'getter'包装到setTimeout()
中,延迟10毫秒,我知道这只是UGLY,但是唯一一个在Chrome中工作的人。
如果你们有任何想法如何更好地解决这个问题我会非常感激。
答案 2 :(得分:13)
尽管Marcus Ekwall对追加的同步性绝对正确,但我也发现在奇怪的情况下,当下一行代码运行时,浏览器有时并没有完全呈现DOM。
在这种情况下,shadowdiver解决方案沿着正确的路线 - 使用.ready - 然而将调用链接到原始追加是非常整洁的。
$('#root')
.append(html)
.ready(function () {
// enter code here
});
答案 3 :(得分:5)
我有另一个可能对某人有用的变体:
$('<img src="http://example.com/someresource.jpg">').load(function() {
$('#login').submit();
}).appendTo("body");
答案 4 :(得分:5)
使用MutationObserver
可以像jQuery append
方法的回调一样:
我在another question中解释过,这次我只会举例说明现代浏览器:
// Somewhere in your app:
var observeDOM = (() => {
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
return function(obj, callback){
if( MutationObserver ){
// define a new observer
var obs = new MutationObserver(function(mutations, observer){
if( mutations[0].addedNodes.length || mutations[0].removedNodes.length )
callback(mutations);
});
// have the observer observe foo for changes in children
obs.observe( obj, { childList:true, subtree:true });
return obs;
}
}
})();
//////////////////
// Your code:
// setup the DOM observer (on the appended content's parent) before appending anything
observeDOM( document.body, ()=>{
// something was added/removed
}).disconnect(); // don't listen to any more changes
// append something
$('body').append('<p>foo</p>');
答案 5 :(得分:3)
我认为这个问题已经得到了很好的解答,但这对于处理“subChild_with_SIZE”更具体(如果它来自父级,但你可以从它的位置进行调整)
$("#root").append(
$('<div />',{
'id': 'child'
})
)
.children()
.last()
.each(function() {
$(this).append(
$('<div />',{
'id': $(this).parent().width()
})
);
});
答案 6 :(得分:3)
我对这里的所有答案感到惊讶......
试试这个:
window.setTimeout(function() { /* your stuff */ }, 0);
注意0超时。它不是一个任意数字......正如我所理解的那样(虽然我的理解可能有些不稳定),但有两个javascript事件队列 - 一个用于宏事件,一个用于微事件。 &#34;更大&#34;作用域队列包含更新UI(和DOM)的任务,而微队列执行快速任务类型操作。
还要意识到设置超时并不能保证代码完全按照指定的值执行。这样做本质上是将函数放入更高的队列(处理UI / DOM的队列),并且在指定的时间之前不运行它。
这意味着将超时设置为0会将其置于javascript事件队列的UI / DOM部分中,以便在下一次可能的情况下运行。
这意味着DOM将使用所有先前的队列项进行更新(例如通过$.append(...);
插入,并且当代码运行时,DOM完全可用。
(p.s。 - 我是从 JavaScript Ninja的秘密中学到的 - 一本优秀的书:https://www.manning.com/books/secrets-of-the-javascript-ninja)
答案 7 :(得分:3)
我遇到了同样的问题并找到了一个简单的解决方案。 在调用附加函数后添加文档准备就绪。
$("#root").append(child);
$(document).ready(function () {
// Action after append is completly done
});
答案 8 :(得分:2)
$.when($('#root').append(child)).then(anotherMethod());
答案 9 :(得分:0)
最干净的方法是逐步进行。使用每个函子来贯穿每个元素。一旦添加了该元素,就将其传递给后续函数以处理该元素。
function processAppended(el){
//process appended element
}
var remove = '<a href="#">remove</a>' ;
$('li').each(function(){
$(this).append(remove);
processAppended(this);
});
答案 10 :(得分:0)
Jquery append函数返回一个jQuery对象,因此您只需在末尾标记方法
$("#root").append(child).anotherJqueryMethod();
答案 11 :(得分:0)
对于图像和其他来源,您可以使用:
$(el).one('load', function(){
// completed
}).each(function() {
if (this.complete)
$(this).load();
});
答案 12 :(得分:-1)
我在为移动设备编码HTML5时遇到了这个问题。某些浏览器/设备组合导致错误,因为.append()方法不能立即反映DOM中的更改(导致JS失败)。
对于这种情况,通过快速和肮脏的解决方案是:
var appint = setInterval(function(){
if ( $('#foobar').length > 0 ) {
//now you can be sure append is ready
//$('#foobar').remove(); if elem is just for checking
//clearInterval(appint)
}
}, 100);
$(body).append('<div>...</div><div id="foobar"></div>');
答案 13 :(得分:-1)
在jquery中,您可以在追加后使用
$(function(){
//code that needs to be executed when DOM is ready, after manipulation
});
$()调用一个函数,该函数注册一个DOM就绪的回调(如果将函数传递给它)或从DOM返回元素(如果将选择器字符串或元素传递给它)
您可以在此处找到更多内容
difference between $ and $() in jQuery
http://api.jquery.com/ready/
答案 14 :(得分:-1)
我最近遇到了类似的问题。我的解决方案是重新创建集合。让我试着证明:
var $element = $(selector);
$element.append(content);
// This Doesn't work, because $element still contains old structure:
$element.fooBar();
// This should work: the collection is re-created with the new content:
$(selector).fooBar();
希望这有帮助!
答案 15 :(得分:-1)
是的,您可以为任何DOM插入添加回调功能:
$myDiv.append( function(index_myDiv, HTML_myDiv){
//....
return child
})
查看JQuery文档:http://api.jquery.com/append/
这是一个实用的,类似的例子:
http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_html_prepend_func
答案 16 :(得分:-1)
我知道这不是最好的解决方案,而是最佳实践:
$("#root").append(child);
setTimeout(function(){
// Action after append
},100);
答案 17 :(得分:-3)
$('#root').append(child);
// do your work here
追加没有回调,这是同步执行的代码 - 不存在未完成的风险
答案 18 :(得分:-4)
$('#root').append(child).anotherMethod();