找到了解决方案!不要费心创建答案
结果我注入了 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();
} );
}