【问题标题】:jQuery object caching behaviorjQuery 对象缓存行为
【发布时间】:2016-09-16 11:22:27
【问题描述】:

我有这个 html:

<div>hi</div>
<div>bye</div>

我使用 jQuery 1.12.3 运行它(我怀疑版本是否重要,但它在这里供参考):

$(document).ready(function(){

    var $divs = $('div');

    alert($divs.length); // Expect 2, get 2

    $('div:first').remove();

    alert($divs.length); // Expect 2, get 2

    // Why does expectation not match reality?
    // Is this not triggering a DOM search?
    alert($($divs).length); // Expect 1, get 2

    $divs = $('div');

    alert($divs.length); // Expect 1, get 1

});

注意:如果你已经做到了,那么请注意我的问题是在 jQuery 代码的 cmets 中。

我确信这相当简单,但我想以通俗的方式了解并希望获得一些直接的文档链接,因为 Google 上的所有内容都会引导我找到无穷无尽的博客文章,这些文章似乎相互复制+粘贴。


另外,为什么会这样?

html

<div>
    <p>1</p>
    <p>2</p>
    <p>3</p>
    <p>4</p>
    <p>5</p>
</div>

jQuery

$(document).ready(function(){

    var $div = $('div');

    alert($div.find('p').length); // expect 5, get 5

    $div.find('p:first').remove();

    alert($div.find('p').length); // expect 5, get 4

});

$div 不应该还包含 5 个&lt;p&gt;s 吗?

.find() 是否会触发对 $div 的 DOM 重新查询?

【问题讨论】:

标签: jquery html caching dom


【解决方案1】:

上线

alert($($divs).length); // Expect 1, get 2

您仍然指的是长度为 2 的原始变量。您将它重新包装为 jquery 对象,但这不会改变它。

要反映 DOM 更改,您必须再次选择。您在最后一次尝试之前执行的操作,并且计数是正确的。

这不是“缓存”行为,而是可变行为。

更新:

至于第二个问题 - find() 确实根据 Pranav C Balan 在他的回答中包含的文档评论进行了 DOM 查询。

【讨论】:

  • 我认为这个答案是正确的,我很乐意接受,但你能看看我的更新吗?
  • 更新了我的答案以解释更多事情。
  • @Starscream1984 : 如果他使用 $('div p:first').remove(); 删除,计数将是 4
  • 感谢更新!但是根据您的“这不会改变 DOM 上的任何内容”。声明,请看jsfiddle.net/c5e1ga1u
  • 道歉 - find 确实查询了 DOM,修改了答案以消除误导性 cmets。我真的应该在回答时仔细检查文档。
【解决方案2】:

$('div:first').remove(); 将从 dom 中删除元素,但 $('div') 不是实时集合,因此不会更新。此外,您正在重新包装根本没有任何效果的现有 jQuery 对象,您可以在 jQuery 库代码上检查它。

在此处了解有关 jQuery 对象的更多信息:The jQuery Object


更新:

根据文档:

给定一个表示一组 DOM 元素的 jQuery 对象,.find() 方法允许我们在 DOM 树中搜索这些元素的后代,并从匹配的元素构造一个新的 jQuery 对象

find() 将遍历元素,然后使用后代生成新的 jQuery 对象。


find 函数的工作原理如下(以下代码取自 jQuery 库)

function( selector ) {
    var i,
        len = this.length,
        ret = [],
        self = this;

    if ( typeof selector !== "string" ) {
        return this.pushStack( jQuery( selector ).filter( function() {
            for ( i = 0; i < len; i++ ) {
                if ( jQuery.contains( self[ i ], this ) ) {
                    return true;
                }
            }
        } ) );
    }

    for ( i = 0; i < len; i++ ) {
        jQuery.find( selector, self[ i ], ret );
    }

    // Needed because $( selector, context ) becomes $( context ).find( selector )
    ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
    ret.selector = this.selector ? this.selector + " " + selector : selector;
    return ret;
},

在基于父级过滤后,最初使用 find 方法中提供的选择器字符串从 dom 中选择元素,因此删除的元素不会被选中。所以find() 只会产生 dom 中存在的元素。


仅供参考:如果对 jQuery 有任何疑问,请先查看他们的文档,即使您不满意,请查看他们的库代码并检查它的工作原理。

【讨论】:

    猜你喜欢
    • 2014-07-07
    • 2012-08-04
    • 2012-07-18
    • 2012-06-06
    • 2012-10-14
    • 2018-05-27
    • 1970-01-01
    • 2012-09-26
    相关资源
    最近更新 更多