从jQuery选择器中过滤元素

Bar*_*ker 2 javascript jquery

我有一个页面,它选择表单中的所有元素并将它们序列化如下:

var filter = 'form :not([name^=ww],[id$=IDF] *,.tools *)';
var serialized = $(filter).serialize();
Run Code Online (Sandbox Code Playgroud)

这是有效的,除非表单大约有600多个元素.然后用户得到javascript错误,说脚本运行缓慢,可能会使他们的浏览器无响应.然后它为他们提供了停止运行脚本的选项.

我试过单独运行过滤器,我尝试在选择器上使用.not,然后序列化它们,但我遇到了两个问题之一.要么它运行得更快而没有错误,但也不会过滤元素,或者它会过滤元素并给我慢速脚本错误.

有任何想法吗?

Jam*_*mes 5

有600多个元素,这将会变得非常缓慢.您需要为Sizzle(jQuery的选择器引擎)提供一些优化机会.

首先,考虑一下jQuery可以使用本机支持的querySelectorAll方法(在现代浏览器中),如果您的选择器符合CSS3规范(或至少达到浏览器当前支持的程度).

对于你的情况,这意味着只传递一个简单的选择器:not而不是3(1个简单,2个复杂).

form :not([name^=ww])
Run Code Online (Sandbox Code Playgroud)

这将是非常快的......虽然你不喜欢不支持的浏览器querySelectorAll.

看看你的选择器,想想Sizzle与每个元素有多少关系.首先,它需要获得页面(你不中的所有元素资格预审:not有标签/类/ id选择).然后,在每个元素上执行以下操作:

(假设如果检查结果为假则退出)

  1. 检查父级是否具有nodeName.toLowerCase()of 的祖先form.
  2. 检查它没有nameww(基本indexOf操作)开头的属性.
  3. 检查它没有以id属性结尾的祖先IDF.(昂贵的操作)
  4. 检查它没有class包含属性的祖先tools.

最后两个操作很慢.

最好手动构建一个filter函数,如下所示:

var jq = $([1]);
$('form :input').filter(function(){

    // Re-order conditions so that
    // most likely to fail is at the top!

    jq[0] = this; // faster than constructing a new jQ obj

    return (

        !jq.closest('[id$=IDF]')[0]
            // this can be improved. Maybe pre-qualify
            // attribute selector with a tag name

        && !jq.closest('.tools')[0]

        && this.name.indexOf('ww') !== 0

    );

});
Run Code Online (Sandbox Code Playgroud)

注意:该功能未经测试.希望你明白了......