.append之后的jQuery函数

Dav*_*rák 83 jquery

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

这是一个例子:

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

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

mek*_*all 65

你在这里有很多有效的答案,但没有一个真正告诉你为什么它的工作原理.

在JavaScript中,命令一次一个地执行,按照它们的顺序同步执行,除非您通过使用超时或间隔明确告诉它们是异步的.

这意味着您的.append方法将被执行,并且在该方法完成其工作之前,将执行其他任何操作(忽略可能存在的任何可能的超时或间隔).

总而言之,不需要回调,因为.append它将同步运行.

  • 这是真的,但这是我的问题:我追加复杂的DOM,并在追加后,我计算根元素的新大小,但在这里我得到错误的数字.并认为,问题是这样的:在DOM还没有完全地加载,只有第一个孩子(.append( "<DIV ID =" 孩子 "> <DIV ID =" subChild_with_SIZE "> </ DIV> </ DIV>")) (36认同)
  • @DavidHorák为什么这是接受的答案?确实,即使发生了变化,代码也不会阻塞,直到完全重新发生时才会惊讶地发现这有32次上升!(或者我甚至不会引起重排)类似答案[here](http:// stackoverflow. com/questions/8840580/force-dom-redraw-refresh-on-chrome-mac)可能与矿石相关. (20认同)
  • 我同意安德烈亚斯,这个答案是不正确的.问题在于,即使append已经返回,该元素仍然可能在DOM中不可用(依赖于浏​​览器,在某些浏览器中有效,在其他浏览器中有效).使用超时仍然不能保证元素将在DOM中. (16认同)

小智 19

好吧,我有完全相同的尺寸重新计算问题,经过几个小时的头痛我不得不反对.append()严格同步的行为.好吧,至少在Google Chrome中.请参阅以下代码.

var input = $( '<input />' );
input.append( arbitraryElement );
input.css( 'padding-left' );
Run Code Online (Sandbox Code Playgroud)

在Firefox中正确检索了padding-left属性,但在Chrome中它是空的.像我想的所有其他CSS属性一样.经过一些实验后,我不得不满足于将''getter'包装成setTimeout()10毫秒的延迟,我知道这只是UGLY,但是唯一一个在Chrome中工作的人.如果你们有任何想法如何更好地解决这个问题,我将非常感激.

  • 这对我很有帮助:http://stackoverflow.com/q/8840580/176140 - 意思是,append()是IS同步的,但DOM更新不是 (13认同)

小智 15

虽然Marcus Ekwall对于追加的同步性是完全正确的,但我也发现在奇怪的情况下,当下一行代码运行时,浏览器有时并不完全呈现DOM.

在这种情况下,shadowdiver解决方案沿着正确的路线 - 使用.ready - 然而将调用链接到原始追加是很整洁的.

$('#root')
  .append(html)
  .ready(function () {
    // enter code here
  });
Run Code Online (Sandbox Code Playgroud)


jle*_*ach 8

我对这里的所有答案感到惊讶......

尝试这个:

window.setTimeout(function() { /* your stuff */ }, 0);
Run Code Online (Sandbox Code Playgroud)

请注意 0 超时。这不是一个任意的数字......据我所知(虽然我的理解可能有点不稳定),有两个 javascript 事件队列 - 一个用于宏事件,一个用于微事件。“较大”范围的队列包含更新 UI(和 DOM)的任务,而微队列执行快速任务类型的操作。

还要意识到设置超时并不能保证代码完全按照指定的值执行。这实际上是将函数放入更高的队列(处理 UI/DOM 的队列),并且不会在指定时间之前运行它。

这意味着将超时设置为 0 会将其放入 javascript 事件队列的 UI/DOM 部分,以在下一个可能的机会运行。

这意味着 DOM 会更新所有先前的队列项(例如通过 插入$.append(...);,并且当您的代码运行时,DOM 完全可用。

(ps - 我从JavaScript Ninja 的 Secrects中学到了这一点- 一本好书:https : //www.manning.com/books/secrets-of-the-javascript-ninja


msa*_*gel 5

我有另一个可能对某人有用的变体:

$('<img src="http://example.com/someresource.jpg">').load(function() {
    $('#login').submit();
}).appendTo("body");
Run Code Online (Sandbox Code Playgroud)


小智 5

我遇到了同样的问题,并找到了一个简单的解决方案。在调用 append 函数后添加准备好的文档。

$("#root").append(child);
$(document).ready(function () {
    // Action after append is completly done
});
Run Code Online (Sandbox Code Playgroud)


vsy*_*ync 5

使用MutationObserver可以像jQuery append方法的回调一样:

我在另一个问题中解释过,这次我只会举例说明现代浏览器:

// 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>');
Run Code Online (Sandbox Code Playgroud)