jQuery .append
が完全に終了した後に関数を呼び出す方法は?
次に例を示します。
$("#root").append(child, function(){
// Action after append is completly done
});
問題:複雑なDOM構造が追加されると、追加関数コールバック内のルート要素の新しいサイズの計算が間違っています。DOMはまだ完全にロードされておらず、追加された複雑なDOMの最初の子だけであることが前提です。
jQuery .append
が完全に終了した後に関数を呼び出す方法は?
次に例を示します。
$("#root").append(child, function(){
// Action after append is completly done
});
問題:複雑なDOM構造が追加されると、追加関数コールバック内のルート要素の新しいサイズの計算が間違っています。DOMはまだ完全にロードされておらず、追加された複雑なDOMの最初の子だけであることが前提です。
回答:
ここには多くの有効な回答がありますが、実際に機能する理由を説明するものはありません。
JavaScriptでは、タイムアウトまたは間隔を使用して非同期であると明示的に指定しない限り、コマンドは一度に1つずつ、実行順に同期して実行されます。
つまり、.append
メソッドが実行され、そのメソッドがそのジョブを完了するまで、他に何も(存在する可能性のあるタイムアウトや間隔を無視して)実行されません。
まとめると、は.append
同期的に実行されるため、コールバックは必要ありません。
さて、私はサイズの再計算でまったく同じ問題を抱えており、何時間もの頭痛の後で、.append()
厳密に同期する動作に同意する必要があります。少なくともGoogle Chromeではそうです。次のコードを参照してください。
var input = $( '<input />' );
input.append( arbitraryElement );
input.css( 'padding-left' );
Firefoxでpadding-leftプロパティは正しく取得されますが、Chromeでは空です。私が思う他のすべてのCSSプロパティと同様に。いくつかの実験を行った後、CSSの「getter」setTimeout()
を10ミリ秒の遅延でラップすることで解決する必要がありました。あなたがこの問題をより良く解決する方法を知っている人がいたら、私はとても感謝しています。
.ready()
はるかに優れたエレガントなソリューションを利用した答えをご覧ください。
Marcus Ekwallは、appendの同時性については完全に正しいですが、奇妙な状況では、次のコード行を実行したときに、ブラウザーによってDOMが完全にレンダリングされないこともあります。
このシナリオでは、shadowdiverソリューションは正しい線に沿って-.readyを使用して-ですが、元の追加への呼び出しをチェーンするのはかなり面倒です。
$('#root')
.append(html)
.ready(function () {
// enter code here
});
ここですべての答えに驚いています...
これを試して:
window.setTimeout(function() { /* your stuff */ }, 0);
タイムアウト0に注意してください。任意の数ではありません...私が理解しているように(私の理解は少し不安定かもしれません)、2つのjavascriptイベントキューがあります-マクロイベント用とマイクロイベント用です。「より大きな」スコープキューは、UI(およびDOM)を更新するタスクを保持し、microキューはクイックタスクタイプの操作を実行します。
また、タイムアウトを設定しても、コードがその指定された値で正確に実行されるとは限らないことに注意してください。これにより、基本的には関数が上位のキュー(UI / DOMを処理するキュー)に入れられ、指定された時間の前に実行されなくなります。
つまり、タイムアウトを0に設定すると、JavaScriptのイベントキューのUI / DOM部分に配置され、次の機会に実行されます。
これは、DOMが以前のすべてのキュー項目(を介して挿入されるなど)で更新され$.append(...);
、コードが実行されると、DOMが完全に使用可能になることを意味します。
(ps-私はこれをJavaScript NinjaのSecrectsから学びました-優れた本:https : //www.manning.com/books/secrets-of-the-javascript-ninja)
setTimeout()
理由がわからないまま何年も追加しています。説明ありがとう!
私は誰かに役立つかもしれない別のバリアントがあります:
$('<img src="http://example.com/someresource.jpg">').load(function() {
$('#login').submit();
}).appendTo("body");
...on('load', function(){ ...
ます:stackoverflow.com/a/37751413/2008111
私は同じ問題に遭遇し、簡単な解決策を見つけました。追加機能を呼び出した後にドキュメントを準備します。
$("#root").append(child);
$(document).ready(function () {
// Action after append is completly done
});
を使用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>');
私はこれはうまく答えられたと思いますが、これは「subChild_with_SIZE」の処理にもう少し具体的です(それが親からのものである場合は、それをどこからでも適用できます)
$("#root").append(
$('<div />',{
'id': 'child'
})
)
.children()
.last()
.each(function() {
$(this).append(
$('<div />',{
'id': $(this).parent().width()
})
);
});
$.when($('#root').append(child)).then(anotherMethod());
$.when
promiseオブジェクトを返すオブジェクトに対してのみ機能します
anotherMethod()
すぐに呼び出すためにのみ機能します。コールバックとして渡されていません。
jquery追加関数はjQueryオブジェクトを返すので、最後にメソッドにタグを付けることができます
$("#root").append(child).anotherJqueryMethod();
モバイルデバイス用の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>');
はい、任意の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
})
.prepend()
メソッドを次のように置き換えることができます:$( "p")。prepend(function(n、pHTML){return "<b> This p element </ b>(\" <i > "+ pHTML +" </ i> \ ")<b>のインデックスは" + n + "</ b>です。";
最近、似たような問題に遭遇しました。私にとっての解決策は、コレクションを再作成することでした。実演してみましょう:
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();
お役に立てれば!
jqueryでは、追加した直後に使用できます
$(function(){
//code that needs to be executed when DOM is ready, after manipulation
});
$()は、DOM対応のコールバックを登録する(関数が渡される場合)、またはDOMから要素を返す(セレクター文字列または要素が渡される場合)関数を呼び出します。
あなたはもっとここに見つけることができます
jQueryので$と$()との差を
http://api.jquery.com/ready/
私はそれが最良の解決策ではないことを知っていますが、ベストプラクティス:
$("#root").append(child);
setTimeout(function(){
// Action after append
},100);
$('#root').append(child);
// do your work here
Appendにはコールバックがなく、これは同期的に実行されるコードです-実行されないリスクはありません
append()
時間はほとんどかかりません。