gpt4 book ai didi

jQuery自定义选择器 "undefined"

转载 作者:行者123 更新时间:2023-12-03 22:59:51 25 4
gpt4 key购买 nike

我正在尝试使jQuery ui日历在单击日期时进行ajax调用,
但是几天前我遇到了一个问题。
我发现了应该执行此操作的代码片段,但是正如我发现的那样,它使用了jQuery自定义选择器。代码给了我一个错误,所以我开始深入研究自定义选择器以了解有关它们的更多信息。到目前为止,我还无法找出为什么我会出现这种奇怪的行为。

这是一张希望可以解决问题的图片,在此之后我将作进一步解释

我已经在控制台中输入了

$('.ui-datepicker-calendar td a:test(3)')

如您所见,我meta2和stack2是未定义的,还有另外一件奇怪的事,为什么index2返回一个#document,它应该包含元素数组的索引。

此外,元素(el2)甚至都不是正确的元素。
看一看,我打电话
$('.ui-datepicker-calendar td a:test(3)')
这应该从日历中选择所有日期,并且在第一个循环中,console.log应该打印出这个日期
<td class=" ui-datepicker-week-end " data-handler="selectDay" data-event="click" data-month="8" data-year="2012"><a class="ui-state-default" href="#">1</a></td>

但是相反,我得到了整个文档中的第一个“a”标签,在这种情况下,它是上个月的一个(如图所示)。

如果有人可以对此情况有所了解,请这样做。
哦,还有我要饶恕的一件事

meta2,它应该包含这个
[
':test(argument)', // full selector
'test', // only selector
'', // quotes used
'argument' // parameters
]

再次在我的情况下,它是不确定的...

我将分享我的JavaScript代码,希望对您有所帮助
<script>
$(function()
{
$.expr[":"].test = function(el2,index2,meta2,stack2)
{
debugger;
console.log(el2);
console.log(index2);
console.log(meta2);
console.log(stack2);
}
})

$(function()
{
function getJsonDate(year, month)
{
$.getJSON('dates.php?year='+year+'&month='+month, function(data)
{
var i = 0;
for (i = 0; i < data.data.length; i++)
{
debugger;
var myDay = data.data[i]['d'];
$('.ui-datepicker-calendar td a:exactly('+data.data[i]['d']+')')
.css({color: '#f00'})
.attr('href',data.data[i]['link'])
.parent().attr('onclick','');
}
});
}
$.expr[":"].exactly = function(el, index, meta, stack)
{
debugger;
console.log(el);
console.log(index);
console.log(meta);
console.log(stack);
var s = meta[3];
if (!s) return false;
return eval("/^" + s + "$/i").test($(el).text());
};
$('#datepicker').datepicker(
{
inline: true,
onSelect: function(dateText, inst)
{
Date.prototype.toString = function () {return isNaN (this) ? 'NaN' : [this.getDate(), this.getMonth(), this.getFullYear()].join('/')}
d = new Date(dateText);
getJsonDate(d.getFullYear(), d.getMonth()+1);
},
onChangeMonthYear: function(year, month, inst)
{
//alert(year);
//alert(month);
getJsonDate(year, month);
}
});
});
</script>

最佳答案

最简短的解释是“jQuery 1.8.0中存在错误,请升级至1.8.1进行修复”,但这并不能完全解决所有问题。

jQuery 1.8.x具有显着升级的“Sizzle”引擎,它是用于选择器的。自定义选择器的调用方式已作为此更改的一部分进行了更改,但此外,许多选择器的处理方式也已更改。关于规则处理顺序的各种假设不再成立,等等。在各种用例中,处理速度也显着提高。

即使在升级到1.8.1时,在处理提供的示例时,您仍然会看到与1.7.2(1.8.x之前的系列中的最新版本)的方式有很大不同。这说明了在选择“页面上的第一个元素”时看到的内容。就是说:您对自定义选择器如何工作的期望不是它们实际如何工作,并且如果您允许循环继续进行(而不是在第一次迭代中调用“debugger;”),您会发现它实际上正在经历所有元素)。简而言之:Sizzle不能保证各种规则将被调用的顺序,只是结果会匹配所有规则。

如果您确定自定义规则的效率不如其他规则(也许是因为您确定其他规则会严重减少匹配的元素的数量),则可以通过选择它们,然后调用.find来强制它们先运行()放在元素的那个子集上,例如:

$(".ui-datepicker-calendar").find("td a:test(3)");

至于未定义的“堆栈”,正如Kevin B指出的那样,尽管1.8.1更新恢复了向后兼容性,但API发生了变化,并且看起来“堆栈”不再只是传递给伪了。实际上,这是有道理的,因为可以更改测试的顺序。那就是:堆栈在到达时是空的,因为“处理任何
元素是否与该伪选择器匹配”是第一个要处理的规则。测试应该始终是独立的,因此无论如何堆栈都不会真正有用(可能只会导致困惑)。

因此,如果1.8.1恢复了向后兼容性,那么用于创建伪选择器的前向兼容方法是什么?在
the documentation for Sizzle's pseudo-selectors中可以看到,从jQuery 1.8开始创建伪选择器的首选方法是“createPseudo”方法($ .expr.createPseudo),该方法更喜欢使用闭包而不是“meta”参数。因此,对于您的特定示例,执行这些操作的"new"方法将是:
$.expr[":"].test = $.expr.createPseudo(function( tomatch )
{
return function( el2 )
{
debugger;
console.log(el2); // not much else to see here
};
})

其中“tomatch”是:test(...)选择器的参数。如您所见,在这种新语法中,不再需要您要查找的额外参数。至于一些有用的东西:
$.expr[":"].exactly = $.expr.createPseudo(function( s )
{
return function(el)
{
if(!s) return false;
return eval("/^" + s + "$/i").test($(el).text());
};
});

此版本的“完全”应该与1.8+兼容,并且是首选的做事方法。

我认为,即使在jQuery版本/api中遇到了麻烦,您提供的代码仍然无法完全满足您的要求,因为datepicker可能会根据插件的想法而重新构建。仍有片刻的时间可以告诉您所需的元素确实按预期突出显示,因此选择器本身确实可以正常工作。

下面是一个完整的示例,基于您提供的示例。通过更改1.7.2、1.8.0和1.8.1之间使用的jQuery版本,可以看到行为上的差异。为了实现跨版本的兼容性,已在伪选择器函数分配中添加了$ .expr.createPseudo测试。注意所有“调试器”;语句已被注释掉,因为在datepicker中所有日期链接的每次迭代中都有一个断点变得很乏味,并且对getJSON调用进行了模拟以允许测试是独立的。
<html>
<head>
<title>jQuery custom selector, "undefined"</title>
<!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script> -->
<!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.js"></script> -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.js"></script>
<link rel="stylesheet"
href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/themes/base/jquery-ui.css" />
<script>
$(function()
{
$.expr[":"].test = $.expr.createPseudo ?
$.expr.createPseudo(function( tomatch )
{
return function( el2 )
{
// debugger;
console.log(el2);
};
}) :
function(el2,index2,meta2,stack2)
{
// debugger;
console.log(el2);
console.log(index2);
console.log(meta2);
console.log(stack2);
};
})

$(function()
{
function getJsonDate(year, month)
{
//$.getJSON('dates.php?year='+year+'&month='+month, function(data)
//{
var data = {data:[
{d:1,link:"a"},
{d:15,link:"b"},
{d:25,link:"c"}
]};
var i = 0;
for (i = 0; i < data.data.length; i++)
{
// debugger;
var myDay = data.data[i]['d'];
$('.ui-datepicker-calendar td a:exactly('+data.data[i]['d']+')').
css({color: '#f00'}).
attr('href',data.data[i]['link']).
parent().attr('onclick','');
}
//});
}

$.expr[":"].exactly = $.expr.createPseudo ?
$.expr.createPseudo(function( s )
{
return function(el)
{
if(!s) return false;
return eval("/^" + s + "$/i").test($(el).text());
};
}) :
function(el, index, meta, stack)
{
// debugger;
console.log(el);
console.log(index);
console.log(meta);
console.log(stack);
var s = meta[3];
if (!s) return false;
return eval("/^" + s + "$/i").test($(el).text());
};

$('#datepicker').datepicker(
{
inline: true,
onSelect: function(dateText, inst)
{
Date.prototype.toString = function () {
return isNaN (this) ?
'NaN' :
[this.getDate(), this.getMonth(), this.getFullYear()].join('/')
}
d = new Date(dateText);
getJsonDate(d.getFullYear(), d.getMonth()+1);
},
onChangeMonthYear: function(year, month, inst)
{
//alert(year);
//alert(month);
getJsonDate(year, month);
return false;
}
});
});
</script>
<script>
(function($){$(function(){
$("<input />").
attr({type:"button", value: "run test selector"}).
click(function(){
$(".ui-datepicker-calendar td:test(3) a");

// Or, if you are certain that your test will be less-efficient than an exclusion based
// on parents, you could do:
// $(".ui-datepicker-calendar").find("td a:test(3)");
}).
appendTo("body");
})}(window.jQuery));
</script>
</head>
<body>
<a href="#ignoreThisLink">.</a>
<a href="#ignoreThisToo">.</a>
<p>
(first, click the input box to cause the datepicker to initialise)
</p>
<input type="text" id="datepicker" />
</body>
</html>

我希望这有助于阐明一些事情。

*我说这是“首选”方法,但是您仍在使用“eval”。不建议这样做,因为它很慢并且可能导致意外/令人惊讶/危险的结果。一种基于字符串构建正则表达式的更好方法是
return (new RegExp("^" + s + "$", "i")).test($(el).text());

尽管即使这样也有问题,但因为“s”可能包含RegExp特殊字符。但是,在这种特殊情况下,甚至不需要使用正则表达式,并且可以通过以下方式更有效地测试事物:
return String(s).toUpperCase() === $(el).text().toUpperCase();

通过将转换滚动到闭包中,您甚至可以节省更多,从而使您具有以下全部功能:
$.expr[":"].exactly = $.expr.createPseudo(function( s )
{
if(!s) return function(){ return false; };
s = String(s).toUpperCase();

return function(el)
{
return (s === $(el).text().toUpperCase());
};
});

关于jQuery自定义选择器 "undefined",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12244929/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com