微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

jQuery自定义选择器,“undefined”

我想在点击日期时让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应该打印出来

但是我得到了整个文档中的第一个“a”标记,在这种情况下是前一个月的标记(如图所示).

如果有人能对这种情况有所了解,请做.
哦,我还有一件事要原谅

meta2,它应该包含这个

[
    ':test(argument)',// full selector
    'test',// only selector
    '',// quotes used
    'argument'         // parameters
]

在我的情况下,它的未定义……

我将分享我的javascript代码,希望它有所帮助

最佳答案
最简短的解释是“jQuery 1.8.0中有一个错误,升级到1.8.1进行修复”,但这并不能完全解决所有问题.

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

即使升级到1.8.1,在处理您提供的示例时,您仍会看到与1.7.2(1.8.x之前的系列中的最新版本)中的内容完全不同.这解释了您在选择“页面上的第一个< a>元素”时所看到的内容.也就是说:你对自定义选择器如何工作的期望不是它们实际工作的方式,如果你允许循环继续(而不是在第一次迭代时调用’debugger;’),你会看到它实际上正在通过所有< a>元件).简而言之:Sizzle不保证将调用各种规则的顺序,只是结果将匹配所有规则.

如果您确定自定义规则的效率低于其他规则(可能是因为您确定其他规则可以严重减少匹配元素的数量),您可以先选择它们,然后调用.find来强制执行这些规则. ()只是元素的子集,例如:

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

至于“堆栈”未定义,正如Kevin B指出的那样,尽管1.8.1更新恢复了向后兼容性,但API已经改变,看起来“堆栈”根本不再传递给伪.实际上,这是有道理的,因为可以调用测试的顺序改变.也就是说:当你到达它时,堆栈是空的,因为“看看是否有任何< a>元素与这个伪选择器匹配”是第一个被处理的规则.测试应始终是自包含的,因此无论如何堆栈都不会非常有用(可能只会导致混淆).

因此,如果1.8.1恢复向后兼容性,那么创建伪选择器的前向兼容方法是什么?正如您在the documentation for Sizzle’s pseudo-selectors中看到的,从jQuery 1.8开始创建伪选择器的首选方法是“createPseudo”方法($.expr.createPseudo),它更喜欢使用闭包而不是“Meta”参数.因此,对于您的特定示例,执行它们的“新”方法将是:

$.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出现问题,您提供的代码仍然无法完全按照您的要求执行,因为日期选择器可能会随着插件的突发奇想而重建.还有一个短暂的时刻,你可以告诉所需的元素确实按预期突出显示,因此选择器本身似乎确实有效.

根据您提供的样本,下面是一个完整的示例.您可以通过更改1.7.2,1.8.0和1.8.1之间使用的jQuery版本来查看行为差异.为了跨版本兼容,$.expr.createPseudo的测试已添加到伪选择器功能分配中.注意所有“调试器”;语句已被注释掉,因为在datepicker中所有日期链接的每次迭代中都有一个断点变得相当繁琐,并且已经模拟了getJSON调用以允许测试自包含.

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,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,inst) 
            {
                Date.prototype.toString = function () {
                    return isNaN (this) ?
                        'NaN' :
                        [this.getDate(),this.getFullYear()].join('/')
                }
                d = new Date(dateText);
                getJsonDate(d.getFullYear(),month);
                return false;
            }
        });
    });
    Could do:
                //  $(".ui-datepicker-calendar").find("td a:test(3)");
            }).
            appendTo("body");
    })}(window.jQuery));
    noreThisLink">.noreThisToo">.irst,click the input Box to cause the datepicker to initialise)
    

我希望这有助于揭示事物.

*我说这是“首选”方法,但您仍在使用“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());
        };
});

原文地址:https://www.jb51.cc/jquery/428628.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐