解決策を見つけました!わざわざ回答を作成しないでください
html を 2 回注入していたことがわかりました。1 回目はセレクターを作成する前で、2回目は未完成のリファクタリングのためです。したがって、DOM の関連部分を上書きします。ただし、キャッシュされたセレクターは依然として古い DOM 部分を参照していたため、ガベージ コレクションの対象から外れていました。もちろん、古い部分を変更しても、新しい部分には何の影響もありませんでした。これは、jQuery に新たに選択を行わせることで明確に示されました。
質問
ウィジェットを作成しようとしています。スクリプトを実行した後、ウィジェットは特定のコード タグ (以下では $rootElem として参照) を持つ を見つけ、HTML コードの一部をダウンロードして、この div に挿入します。これを行った後、入力要素へのイベントのアタッチ、スライダーなどの UI 要素の構築を開始します。
私の知る限り、html を DOM に挿入した後、結果の DOM は、最初から html を持っているのと同じになるはずです。jQuery は別のことを考えていることがわかりました。具体的に言うと、最初に html を挿入し、次にセレクターの結果を見つけてキャッシュし始めます。
次のコード ブロックは同等である必要があります (同じことを行います)。のような html の一部を のような<span>awaiting calculation ...</span>
ものに変更し<span>1234</span>
ます。そして、見よ、すべての html を同じドキュメントに入れると (挿入するのではなく)、実際には同じことを行っています。
後で取得するためにセレクターの結果をキャッシュする
var $result = $rootElem.find( "div.result p:nth-of-type(1) span" );
$.subscribe( "/server/calculateLoan/finished", function ( e, firstPayment ) {
$result.text( firstPayment ) );
} );
毎回セレクションを行う
$.subscribe( "/server/calculateLoan/finished", function ( e, firstPayment ) {
$rootElem.find( "div.result p:nth-of-type(1) span" ).text( firstPayment ) );
} );
しかし、ウィジェットの HTML コードをメイン ドキュメントから移動し、それを操作する前に挿入すると、キャッシュされていない (後者の) バージョンのみが機能します。実際、最初のものもうまくいくようです。匿名関数にブレークポイントを設定すると、奇妙なことが起こっていることがわかります。
> $result.text()
<span>awaiting calculation ...</span>
> $rootElem.find( "div.result p:nth-of-type(1) span" ).text()
<span>awaiting calculation ...</span>
> $result.text("1234") //This is not showing in the browser window!
[<span>1234</span>]
> $result.text() //This is not showing in the browser window!
[<span>1234</span>]
> $($result.selector).text() //What kind of magic is this?!
<span>awaiting calculation ...</span>
> $rootElem.find( "div.result p:nth-of-type(1) span" ).text()
<span>awaiting calculation ...</span>
同じ要素を検索する場合よりも、キャッシュされた jQuery セレクターが別の DOM 要素 (変更は表示されていません) を指しているように見えます。これは、ウィジェットの html がページにコピー アンド ペーストされた場合ではなく、html を挿入する場合にのみ発生します。何が起こっているのか説明したい人はいますか?
これは、Chrome と Firefox の両方で発生します。
メイン ページの html ビットは次のようになります。
<div id="widget_calculator"><!-- dynamic fetch --> </div>
ウィジェットの html
<h1>Widget calculator</h1>
<div class="user-inputs">...</div>
<div class="result">
<p><span>awaiting calculation ...</span></p>
</div>
html を挿入するコード
function fetchHtmlTemplate( templateUrl ) {
// set globals
$ = jQuery;
$rootElem = $( "#widget_calculator" );
$.get( templateUrl, function ( htmlTemplate ) {
$rootElem.html( htmlTemplate );
buildWidget();
} );
}