如何刷新存储和快照的jquery选择器变量

时间:2012-08-08 16:23:30

标签: javascript jquery variables dom jquery-selectors

我昨天遇到了一个问题,一个jquery-selector我分配给一个变量,这让我很生气。

这是一个带有testcase的jsfiddle:

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

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

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

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

6 个答案:

答案 0 :(得分:58)

是的,这是一个快照。此外,从页面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

答案 1 :(得分: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;
};

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

答案 2 :(得分:0)

不推荐使用Jquery .selector,在分配

时,最好将带有选择器值的字符串记忆到某个变量
function someModule($selector, selectorText) {
   var $moduleSelector = $selector;
   var moduleSelectorText = selectorText;

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

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

答案 3 :(得分:0)

如果您使用remove(),它将仅删除DOM的一部分,但不会删除所有子项或相关的部分,相反,如果您在元素上使用empty()则问题就消失了。

E.G:

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

也许这对某人有用!

答案 4 :(得分:0)

干净且通用的解决方案可以在jQuery 3.4.1中正常使用:

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

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

定义:

self.bias = nn.Parameter(torch.rand(1,1))

用法:

$ = (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 

答案 5 :(得分:0)

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

在此示例中,我使用了不带括号的箭头功能,该功能会返回箭头旁边的任何内容。在这种情况下,它将返回JQuery集合。

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