0

解決策を見つけました!わざわざ回答を作成しないでください

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

0 に答える 0