33

我昨天遇到了一个分配给变量的 jquery-selector 问题,这让我发疯。

这是一个带有测试用例的jsfiddle:

  • 将 .elem 分配给我的 obj var
  • 将两个长度都记录到控制台。结果 => 4
  • 从 DOM 中移除 #3
  • 将obj记录到控制台=>删除的#3仍然存在,长度仍然是4。我发现jquery查询是快照的?到变量,不能?不会?被更新
  • 将 .elem 记录到控制台.. 是的 Result => 3 并且 #3 消失了
  • 现在我用 300 的新宽度更新 .elem
  • 记录 obj & obj.width 给了我 300 .. 所以快照已经更新了?有趣的是 4 个 div 中的 3 个具有新的宽度,但删除的 #3 没有...

另一个测试:将 li 元素添加到 domtree 并记录 obj 和 .elem。.elem 确实有新的 li 而 obj 没有,因为它仍然是旧快照

http://jsfiddle.net/CBDUK/1/

没有办法用新内容更新这个 obj 吗?我不想创建一个新的 obj,因为在我的应用程序中有很多信息保存在该对象中,我不想破坏......

4

6 回答 6

64

是的,这是一个快照。此外,从页面 DOM 树中删除一个元素并不会神奇地消除对该元素的所有引用。

您可以像这样刷新它:

var a = $(".elem");

a = $(a.selector);

迷你插件:

$.fn.refresh = function() {
    return $(this.selector);
};

var a = $(".elem");

a = a.refresh();

不过,这个简单的解决方案不适用于复杂的遍历。您将不得不为该.selector属性创建一个解析器以刷新这些属性的快照。

格式如下:

$("body").find("div").next(".sibling").prevAll().siblings().selector
//"body div.next(.sibling).prevAll().siblings()"

就地迷你插件:

$.fn.refresh = function() {
    var elems = $(this.selector);
    this.splice(0, this.length);
    this.push.apply( this, elems );
    return this;
};

var a = $(".elem");
a.refresh() //No assignment necessary
于 2012-08-08T16:26:41.180 回答
1

我也喜欢@Esailija 解决方案,但似乎 this.selector 有一些过滤器错误。所以我修改了我的需要,也许它会对某人有用

这是针对 jQuery 1.7.2 没有在更高版本的过滤快照上测试刷新

$.fn.refresh = function() { // refresh seletor
    var m = this.selector.match(/\.filter\([.\S+\d?(\,\s2)]*\)/); // catch filter string
    var elems = null;
    if (m != null) { // if no filter, then do the evarage workflow
        var filter = m[0].match(/\([.\S+\d?(\,\s2)]*\)/)[0].replace(/[\(\)']+/g,'');
        this.selector = this.selector.replace(m[0],''); // remove filter from selector
        elems = $(this.selector).filter(filter); // enable filter for it
    } else {
        elems = $(this.selector);
    }
    this.splice(0, this.length);
    this.push.apply( this, elems );
    return this;
};

代码不是那么漂亮,但它适用于我的过滤选择器。

于 2013-04-17T10:16:06.337 回答
1

干净和通用的解决方案与 jQuery 3.4.1 一起正常工作:

我的解决方案是执行以下操作:

  1. 在 jQuery 对象初始化时拦截选择器,同时使用继承透明地维护所有其他 jQuery 功能
  2. 构建使用我们在初始化期间添加的新“选择器”属性的刷新插件

定义:

$ = (function (originalJQuery) 
{
    return (function () 
    {
        var newJQuery = originalJQuery.apply(this, arguments);
        newJQuery.selector = arguments.length > 0 ? arguments[0] : null;
        return newJQuery;
    });
})($);

$.fn = $.prototype = jQuery.fn;

$.fn.refresh = function () 
{
    if (this.selector != null && (typeof this.selector === 'string' || this.selector instanceof String))
    {
        var elems = $(this.selector);
        this.splice(0, this.length);
        this.push.apply(this, elems);
    }
    return this;
};

用法:

var myAnchors = $('p > a');
//Manipulate your DOM and make changes to be captured by the refresh plugin....
myAnchors.refresh();
//Now, myAnchors variable will hold a fresh snapshot 

注意: 作为优化,对象选择器不需要刷新,因为它们本质上是通过引用传递的,因此,在刷新插件中,我们仅在选择器是字符串选择器而不是对象选择器时才刷新,以便澄清,考虑以下代码:

// Define a plain object
var foo = { foo: "bar", hello: "world" };
 
// Pass it to the jQuery function
var $foo = $( foo );
 
// Test accessing property values
var test1 = $foo.prop( "foo" ); // bar

// Change the original object
foo.foo = "koko";

// Test updated property value
var test2 = $foo.prop( "foo" ); // koko
于 2020-06-20T14:30:31.517 回答
0

Jquery .selector 已弃用,最好在分配时将带有选择器值的字符串记住到某个变量

function someModule($selector, selectorText) {
   var $moduleSelector = $selector;
   var moduleSelectorText = selectorText;

   var onSelectorRefresh = function() {
      $moduleSelector = $(moduleSelectorText);
   }
}

https://api.jquery.com/selector/

于 2017-03-14T11:50:50.390 回答
0

如果你使用remove()它只会删除 DOM 的一部分,而不是所有的子元素或相关的,相反,如果你empty()在元素上使用,问题就消失了。

例如:

 $('#parent .child).find('#foo').empty();

也许它对某人有用!

于 2017-08-15T13:49:18.140 回答
0

您还可以在函数中返回 JQuery 选择器,并将此函数保存到变量中。您的代码看起来会有些不同,但它可以工作。每次执行该函数时,您的 jquery 选择器都会再次搜索 DOM。

在这个例子中,我使用了一个不带括号的箭头函数,它将返回箭头旁边的任何内容。在这种情况下,它将返回 JQuery 集合。

const $mySelector = () => $('.selector');
console.log($mySelector().last().text());
$('.parent').append('<li class="selector">4</li>')

console.log($mySelector().last().text()); //RETURNS 4 not 3
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="parent">
    <li class="selector">1</li>
    <li class="selector">2</li>
    <li class="selector">3</li>
</ul>

于 2020-07-01T14:48:32.913 回答