.append 후 jQuery 함수


92

jQuery .append가 완전히 완료된 후 함수를 호출하는 방법 은 무엇입니까?

예를 들면 다음과 같습니다.

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

문제 : 복잡한 DOM 구조가 추가되면 추가 함수 콜백 내에서 루트 요소의 새 크기 계산이 잘못되었습니다. DOM은 아직 완전히로드되지 않았으며 추가 된 복잡한 DOM의 첫 번째 자식 만로드된다는 가정입니다.


당신은 미세 체인 이벤트 여야합니다. append()시간이 거의 걸리지 않습니다.
Bojangles

stackoverflow.com/q/8840580/176140 참조 (웹킷 브라우저의 DOM '리플 로우')
schellmax

답변:


71

여기에 유효한 답이 많이 있지만 그 중 어느 것도 실제로 작동하는 이유를 알려주지 않습니다.

JavaScript에서 명령은 시간 초과 또는 간격을 사용하여 명시 적으로 비 동기화하도록 지시하지 않는 한 순서대로 동기식으로 한 번에 하나씩 실행됩니다.

즉, .append메서드가 실행되고 해당 메서드가 작업을 완료 할 때까지 다른 어떤 것도 실행되지 않습니다 (존재할 수있는 잠재적 인 제한 시간 또는 간격에 관계없이).

요약하면 .append동 기적으로 실행 되므로 콜백이 필요하지 않습니다 .


40
이것은 모두 사실이지만 여기에 내 문제가 있습니다. 복잡한 DOM을 추가하고 추가 한 직후에 루트 요소의 새 크기를 계산하지만 여기서는 잘못된 숫자를 얻었습니다. 그리고 문제는 이것입니다. DOM의 아직 완전히로드되지 않고 첫 번째 자식 만 (.append ( "<div id ="child "> <div id ="subChild_with_SIZE "> </ div> </ div>"))
David Horák

@JinDave, 당신이 말하는 이 크기 는 무엇입니까 ? 자녀의 수, 부모의 키 또는 계산해야 할 것은 무엇입니까?
mekwall

1
@ 마커스 - ekwall jsfiddle.net/brszE/3 에만 코드를 작동하지 않는, 방법을 쓰고,
데이비드 HORAK

22
@ DavidHorák 그렇다면 이것이 왜 받아 들여지는 대답입니까? 변경이 발생하더라도 완전한 리플 로우가 32 개의 업 보트를 가지고 있다는 사실을 놀라게 할 때까지 코드가 차단되지 않는다는 것은 사실입니다! (또는 리플 로우를 유발하지도 않습니다) [여기] ( stackoverflow.com/questions/ 8840580 /… ) 광석과 관련이있을 수 있습니다.
Andreas

17
나는 Andreas에 동의합니다.이 대답은 정확하지 않습니다. 문제는 append가 반환되었지만 요소가 DOM에서 여전히 사용 가능하지 않을 수 있다는 것입니다 (브라우저에 따라 다르며 일부 브라우저에서는 작동하며 다른 브라우저에서는 중단됨). 타임 아웃을 사용해도 요소가 DOM에 있다는 보장은 없습니다.
Severun

21

Marcus Ekwall은 추가의 동시성에 대해 절대적으로 옳지 만, 이상한 상황에서 다음 코드 줄이 실행될 때 브라우저에서 DOM이 완전히 렌더링되지 않는 경우도 있음을 발견했습니다.

이 시나리오에서 shadowdiver 솔루션은 .ready를 사용하여 올바른 라인을 따르지만 호출을 원래 추가에 연결하는 것이 훨씬 깔끔합니다.

$('#root')
  .append(html)
  .ready(function () {
    // enter code here
  });

1
이것은 모든 상황에서 절대적으로 거짓이며 쓸모가 없습니다. api.jquery.com/ready
Kevin B

안녕 케빈, 어떤면에서?
Daniel-SDS Group

문서가 아직 준비되지 않은 경우에만 단순히 settimeout을 사용하여 얻을 수있는 것보다 더 이상 추가 된 요소를 "렌더링"하기 위해 .ready를 사용하는 것의 이점이 없습니다. 문서가 준비되면 코드가 동기식으로 실행되므로 유용한 영향이 없습니다.
Kevin B

나는 준비가 추가 된 문서가로드되기를 기다리지 않고 대신 전체 DOM이로드 될 때까지 기다릴 것이라고 생각합니다. 이 답변을 쓴 지 약 3 년이 지났지 만 위의 섀도우 다이버에 대해 더 많이 언급 한 것 같지만 당시에는 언급 할 시설이 없었습니다.
Daniel-SDS Group

1
실제로 이것은 예상보다 잘 작동합니다. 여기에 다른 어떤 대답보다 낫습니다.
Blue

20

크기 재계 산과 똑같은 문제가 있으며 몇 시간 동안 두통을 겪은 후에는 .append()엄격하게 동기식 으로 행동하는 것에 동의하지 않습니다 . 적어도 구글 크롬에서는. 다음 코드를 참조하십시오.

var input = $( '<input />' );
input.append( arbitraryElement );
input.css( 'padding-left' );

padding-left 속성은 Firefox에서 올바르게 검색되지만 Chrome에서는 비어 있습니다. 내가 생각하는 다른 모든 CSS 속성과 마찬가지로. 몇 가지 실험 후 나는 CSS 'getter'를 setTimeout()10ms 지연 으로 래핑하는 데 안주해야 했지만 지옥처럼 추악하지만 Chrome에서 작동하는 유일한 것입니다. 이 문제를 더 나은 방법으로 해결하는 방법에 대한 아이디어가 있다면 매우 감사하겠습니다.


15
이것은 나에게 많은 도움이 : stackoverflow.com/q/8840580/176140 - 의미, APPEND ()가 동기를하지만, DOM 업데이트하지 않습니다
schellmax

이 경우 setTimeout은 추악하지 않습니다 (10ms 만 해당). "dom"조작을 요청할 때마다 크롬은 코드가 종료 될 때까지 기다렸다가 실행합니다. 따라서 item.hide 다음에 item.show를 호출하면 아무 작업도 수행하지 않습니다. 실행 함수가 끝나면 DOM에 변경 사항을 적용합니다. 계속하기 전에 "dom"업데이트를 기다려야하는 경우 CSS / DOM 작업을 수행 한 다음 settimeout (function () {다음에 수행 할 작업});을 호출합니다. settimeout은 vb6에서 좋은 오래된 "doevents"처럼 작동합니다! 브라우저에 대기 작업 (DOM 업데이트)을 수행하도록 지시하고 이후에 코드로 돌아갑니다.
foxontherock

.ready()훨씬 더 좋고 우아한 솔루션을 사용하는 답변을 참조하십시오 .
Mark Carpenter Jr.

8

여기에있는 모든 답변에 놀랐습니다 ...

이 시도:

window.setTimeout(function() { /* your stuff */ }, 0);

0 시간 초과에 유의하십시오. 그것은 임의의 숫자가 아닙니다 ... 내가 이해하는 바와 같이 (내 이해가 약간 흔들릴 수 있지만) 두 개의 자바 스크립트 이벤트 큐가 있습니다. 하나는 매크로 이벤트 용이고 다른 하나는 마이크로 이벤트 용입니다. "큰"범위의 대기열은 UI (및 DOM)를 업데이트하는 작업을 보유하고 마이크로 대기열은 빠른 작업 유형 작업을 수행합니다.

또한 시간 제한을 설정한다고해서 코드가 지정된 값에서 정확히 수행되는 것은 아닙니다. 이것이하는 일은 본질적으로 함수를 더 높은 큐 (UI / DOM을 처리하는 큐)에 넣고 지정된 시간 전에 실행하지 않는 것입니다.

즉, 시간 제한을 0으로 설정하면 자바 스크립트 이벤트 큐의 UI / DOM 부분에 배치되어 다음 가능한 기회에 실행됩니다.

즉, DOM이 이전의 모든 대기열 항목 (예 :를 통해 삽입 됨)으로 업데이트되고 $.append(...);코드가 실행될 때 DOM을 완전히 사용할 수 있습니다.

(ps- Secrects of the JavaScript Ninja 에서 배웠습니다 -훌륭한 책 : https://www.manning.com/books/secrets-of-the-javascript-ninja )


나는 setTimeout()이유를 모른 채 몇 년 동안 추가 했습니다. 설명 해주셔서 감사합니다!
steampowered

5

누군가에게 유용 할 수있는 또 다른 변형이 있습니다.

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

1
이것이 더 이상 사용되지 않고 제거되었다고 생각하는 사람들에게는 맞지만 여전히 ...on('load', function(){ ... 여기에서 볼 수있는 것처럼 사용할 수 있습니다. stackoverflow.com/a/37751413/2008111
caramba

5

나는 같은 문제를 발견하고 간단한 해결책을 찾았습니다. 추가 기능을 호출 한 후 문서를 준비합니다.

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


좋은. 이것은 나를 위해 일했습니다 (Handlebars와 JSON을 사용하여 HTML을 추가했으며 물론 일반 문서 준비가 너무 일찍 발생했습니다).
Katharine Osborne

1
@KatharineOsborne 이것은 "일반 문서 준비"와 다르지 않습니다. document.ready는 특정 시나리오에서만 호출되며 다르게 사용한다고해서 다르게 작동하지는 않습니다.
Kevin B

제가 코멘트를 남긴 지 1 년이 넘었지만 IIRC, 당신이 이것을 어디라고 부르는지의 맥락이 중요합니다 (즉, 함수에서). 나는 그것을에 액세스 할 필요가 없습니다 코드는 이후 클라이언트까지 전달되어 더 이상 다시 파고합니다.
캐서린 오스본

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>');

+1. 모든 답변 중에서 귀하의 답변이 가장 적합합니다. 그러나 내 경우에는 무한 루프로 들어가기 때문에 다양한 행을 테이블에 추가하여 작동하지 않았습니다. 테이블을 정렬하는 플러그인은 DOM을 변경하여 관찰자를 무한히 호출합니다.
Azevedo

@Azevedo-왜 무한할까요? 유한하다고 확신합니다. 어쨌든 약간 창의적이어서 추가 된 행 "이벤트"에서 정렬 기능을 분리 할 수 ​​있습니다 . 방법이 있습니다.
vsync

정렬 플러그인이 테이블을 정렬 할 때 관찰자 (dom 변경됨)를 트리거하고 정렬을 다시 트리거합니다. 이제 생각하고 있습니다 ... 테이블 행을 세고 행 카운터가 변경된 경우에만 관찰자가 분류기를 호출하도록 할 수 있습니다.
Azevedo

3

나는 이것이 잘 대답되었다고 생각하지만 이것은 "subChild_with_SIZE"를 처리하는 데 좀 더 구체적입니다 (부모로부터 온 것이지만 그것이있는 곳에서 그것을 조정할 수 있다면)

$("#root").append(
    $('<div />',{
        'id': 'child'
    })
)
.children()
.last()
.each(function() {
    $(this).append(
        $('<div />',{
            'id': $(this).parent().width()
        })
    );
});

2

$.when($('#root').append(child)).then(anotherMethod());


8
$.when단지 그 약속 개체를 반환하는 개체에 대한 작업
아파 드

그것은 "다음 함수가 아닙니다".. 작동하지만 콘솔에 오류를주고 있어요
카란 Datwani

1
이것은 anotherMethod()즉시 호출하기 때문에 작동합니다 .. 콜백으로 전달되지 않습니다.
yts

이것은 말이되지 않습니다.
Kevin B

1

Jquery 추가 함수는 jQuery 객체를 반환하므로 끝에 메소드에 태그를 지정할 수 있습니다.

$("#root").append(child).anotherJqueryMethod();

.append 후 사용자 지정 자바 스크립트 함수를 호출해야합니다. 루트 크기를 다시 계산해야합니다
David Horák

jQuery each 메서드를 사용할 수 있지만 append는 동기 메서드이므로 다음 줄에서 필요한 모든 작업을 수행해도됩니다.
Dve

@JinDave, 정확히 무엇을 재 계산해야합니까? 자녀의 수, 부모의 키 또는 크기 는 무엇을 의미합니까?
mekwall

0

이미지 및 기타 소스의 경우 다음을 사용할 수 있습니다.

$(el).one('load', function(){
    // completed
}).each(function() {
    if (this.complete)
        $(this).load();
});

0

가장 깨끗한 방법은 단계별로 수행하는 것입니다. 각 기능을 사용하여 각 요소를 터트립니다. 해당 요소가 추가되는 즉시 후속 함수에 전달하여 해당 요소를 처리합니다.

    function processAppended(el){
        //process appended element
    }

    var remove = '<a href="#">remove</a>' ;
    $('li').each(function(){
        $(this).append(remove);   
        processAppended(this);    
    });​

-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>');

코드 생성자가 완료되기를 기다리는 데 간격을 사용해서는 안됩니다. 완전히 신뢰할 수 없습니다.
게이브 Hiemstra

-1

예 , 모든 DOM 삽입에 콜백 함수를 추가 할 있습니다. JQuery 문서에서 확인 : http://api.jquery.com/append/ 그리고 여기에 실용적인 유사한 예가 있습니다. http://www.w3schools.com/jquery/ tryit.asp? filename = tryjquery_html_prepend_func
$myDiv.append( function(index_myDiv, HTML_myDiv){ //.... return child })



w3schools 예제를 살펴보면 두 번째 매개 변수를 확인할 수 있습니다. .prepend()메소드를 $ ( "p"). prepend (function (n, pHTML) {return "<b> This p element </ b> (\"<i > "+ PHTML +"</ I> \ ") <B는> 인덱스가"+ N + "</ B>.";
페드로 페레이라

1
당신은 명확하게 내용을 말하는 콜백이 추가 된없는 그 example..it의 목적을 이해하지 못하고, 오히려 콜백 함수를 반환하는 입니다가 추가 될 수 있습니다.
vsync

@vsync : 확실히. 당신은 분명히 내 대답을 이해하지 못했습니다. "아이는" 어떤 추가 된 및 하지 가 추가되었을 때.
Pedro Ferreira

-1

최근 비슷한 문제가 발생했습니다. 나를위한 해결책은 colletion을 다시 만드는 것이 었습니다. 시연 해 보겠습니다.

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

도움이 되었기를 바랍니다!


도움이되지 않았습니다. :(
Pal

-1

jquery에서는 추가 직후에 사용할 수 있습니다.

$(function(){
//code that needs to be executed when DOM is ready, after manipulation
});

$ ()는 DOM 지원 콜백 (함수가 전달 된 경우)을 등록하거나 DOM에서 요소를 반환하는 (선택자 문자열 또는 요소가 전달 된 경우) 함수를 호출합니다.

jQuery에서 $와 $ ()의 차이점을 더 찾을 수 있습니다.

http://api.jquery.com/ready/


-2

최선의 해결책은 아니지만 모범 사례는 다음과 같습니다.

$("#root").append(child);

setTimeout(function(){
  // Action after append
},100);

8
나는 이것이 좋은 습관이라고 생각하지 않습니다. 100은 임의의 숫자이며 이벤트는 더 오래 걸릴 수 있습니다.
JasTonAChair 2015 년

1
갈 길이 잘못되었습니다. 항상이 100ms을하지 않을 수 있습니다
axelvnk

이것이 작동하는 이유에 대한 설명은 여기 내 대답을 참조하십시오 (숫자는 100이 아닌 0 일 수 있음 /되어야 함) : stackoverflow.com/questions/6068955/…
jleach

1
.ready를 사용하는 답변보다 적어도 더 나은 연습입니다.
Kevin B

-4
$('#root').append(child);
// do your work here

Append에는 콜백이 없으며 이는 동 기적으로 실행되는 코드입니다. 수행되지 않을 위험이 없습니다.


3
이런 댓글이 너무 많아 도움이되지 않습니다. @david가 떨어졌습니다. 예, JS는 동기화되어 있지만 DOM은 업데이트하는 데 시간이 필요합니다. DOM 추가 요소를 조작해야하지만 요소가 아직 DOM에 렌더링되지 않은 경우 추가가 완료 되더라도 새 조작이 작동하지 않습니다. (예 : $ ( '# element'). on ().
NoobishPro

-4
$('#root').append(child).anotherMethod();

1
나는 나에게 자바 스크립트 함수,하지의 jQuery 함수를 호출 할 필요가
데이비드 HORAK
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.