0

找到了解决方案!不要费心创建答案

结果我注入了 html 两次——一次是在创建选择器之前,然后,由于一些未完成的重构,第二次;从而覆盖 DOM 的相关部分。不过,缓存的选择器仍然引用旧的 DOM 部分,因此不会被垃圾收集。当然,更改旧部分对新部分没有影响,让 jQuery 重新进行选择清楚地表明了这一点。

问题

我正在尝试创建一个小部件。运行它的脚本后,小部件找到一个带有特定代码标签(在下面引用为 $rootElem),下载一段 html 代码并将其注入到这个 div 中。完成此操作后,它开始将事件附加到输入元素,构建 ui 元素,如滑块等。

AFAIK,在将 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