.append之后的jQuery函数

时间:2011-05-20 07:46:55

标签: jquery

如何在jQuery .append完成后调用函数?

以下是一个例子:

$("#root").append(child, function(){
   // Action after append is completly done
});

问题:当附加复杂的DOM结构时,在追加函数回调中计算根元素的新大小是错误的。假设DOM仍然没有完全加载,只有添加的复杂DOM的第一个孩子是。

19 个答案:

答案 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();