jQuery:选择器特异性是否会提高 .on() 委托的性能?
jQuery: Does selector specificity increase performance with .on() delegation?
在使用 .on()
增加委托事件绑定的特异性时是否有性能提升?
如何测试这个?
例如,第二个语句是否比第一个语句更高效:
$('.foo').on('mouseenter', ':has(.other)', function (e) {
console.log(e);
});
$('.bar').on('mouseenter', 'button:has(.other)', function (e) {
console.log(e);
});
$('.foo').on('mouseenter', ':has(.other)', function (e) {
console.log(e);
});
$('.bar').on('mouseenter', 'button:has(.other)', function (e) {
console.log(e);
});
.foo, .bar {
margin: 2em auto;
text-align: center;
}
<div class="foo">
<button type="button">Hello
<span class="other">World</span>
</button>
</div>
<div class="bar">
<button type="button">Hello
<span class="other">World</span>
</button>
</div>
我主要担心的是,通过委派监听 mouseenter
事件会消耗性能,如果有一种方法可以测试此类事件处理程序的性能。
更新
我应该澄清一下,我并不是要了解一般使用委托对性能的影响。我希望了解在用户交互期间使用 mouseenter
的委托对性能的影响(因为用户的鼠标在绑定元素中同时输入委托和非委托元素),以及是否通过使用更多来提高性能委派的特定选择器。
我倾向于假设没有,因为在根据委托选择器检查之前,每个事件都必须冒泡到绑定元素。
但是有没有办法对此进行测试?
具体有帮助……一点点。
根据 this JSPerf test,在已发布的示例中向选择器添加特定性会持续提高重复测试的性能,但可以想象,在用户交互级别,事件在相对较小的范围内偶尔发生,收益可以忽略不计迭代。
在一些测试中,差异足够小并且在误差范围内,可以被认为是统计等效的。
处理程序中的选择器过滤有问题
但最令人惊讶的结果是上面一位评论者建议的辅助第三次测试,该测试从选择器中取出 :has()
并用回调函数中的 .has()
检查替换它,它始终比在选择器中使用 :has()
执行得慢 — 通常每秒执行 100 次或更多操作。
考虑到 jQuery documentation for :has()
表明您应该期待更好的性能,这可以说是不容忽视的,尤其值得注意:
Because :has()
is a jQuery extension and not part of the CSS
specification, queries using :has()
cannot take advantage of the
performance boost provided by the native DOM querySelectorAll()
method. For better performance in modern browsers, use $(
"your-pure-css-selector" ).has( selector/DOMElement )
instead.
我不怀疑在 .has()
仅用于减少匹配元素集的选择器语句中,人们可以获得更好的性能;但我怀疑测试中显示的性能消耗是通过将 .has()
检查移动到事件数据正在传递的事件处理程序中打破该约定的结果,一个新的 jQuery 对象正在构造this
,并且 .length
正在 if
语句中被访问和检查。
测试配方
为了制定测试,配置了三个事件绑定基准并应用于相同的 HTML 标记,然后是相同的事件触发测试用例——模拟用户将鼠标悬停在各种委托和非委托元素上屏幕 — 应用于三个基准中的每一个以进行比较。
基准1:
$('.foo').on('mouseenter', ':has(.other)', function(e) {
console.log(e);
});
基准2:
$('.foo').on('mouseenter', 'button:has(.other)', function(e) {
console.log(e);
});
基准3:
$('.foo').on('mouseenter', 'button', function(e) {
if ($(this).has('.other').length) {
console.log(e);
}
});
HTML:
<div class="foo">
<button type="button" id="A">some text</button>
<button type="button" id="B"><span class="other">some text</span></button>
<div id="C">some text</div>
</div>
测试用例:
$('#A').trigger('mouseenter');
$('#B').trigger('mouseenter');
$('#C').trigger('mouseenter');
在使用 .on()
增加委托事件绑定的特异性时是否有性能提升?
如何测试这个?
例如,第二个语句是否比第一个语句更高效:
$('.foo').on('mouseenter', ':has(.other)', function (e) {
console.log(e);
});
$('.bar').on('mouseenter', 'button:has(.other)', function (e) {
console.log(e);
});
$('.foo').on('mouseenter', ':has(.other)', function (e) {
console.log(e);
});
$('.bar').on('mouseenter', 'button:has(.other)', function (e) {
console.log(e);
});
.foo, .bar {
margin: 2em auto;
text-align: center;
}
<div class="foo">
<button type="button">Hello
<span class="other">World</span>
</button>
</div>
<div class="bar">
<button type="button">Hello
<span class="other">World</span>
</button>
</div>
我主要担心的是,通过委派监听 mouseenter
事件会消耗性能,如果有一种方法可以测试此类事件处理程序的性能。
更新
我应该澄清一下,我并不是要了解一般使用委托对性能的影响。我希望了解在用户交互期间使用 mouseenter
的委托对性能的影响(因为用户的鼠标在绑定元素中同时输入委托和非委托元素),以及是否通过使用更多来提高性能委派的特定选择器。
我倾向于假设没有,因为在根据委托选择器检查之前,每个事件都必须冒泡到绑定元素。
但是有没有办法对此进行测试?
具体有帮助……一点点。
根据 this JSPerf test,在已发布的示例中向选择器添加特定性会持续提高重复测试的性能,但可以想象,在用户交互级别,事件在相对较小的范围内偶尔发生,收益可以忽略不计迭代。
在一些测试中,差异足够小并且在误差范围内,可以被认为是统计等效的。
处理程序中的选择器过滤有问题
但最令人惊讶的结果是上面一位评论者建议的辅助第三次测试,该测试从选择器中取出 :has()
并用回调函数中的 .has()
检查替换它,它始终比在选择器中使用 :has()
执行得慢 — 通常每秒执行 100 次或更多操作。
考虑到 jQuery documentation for :has()
表明您应该期待更好的性能,这可以说是不容忽视的,尤其值得注意:
Because
:has()
is a jQuery extension and not part of the CSS specification, queries using:has()
cannot take advantage of the performance boost provided by the native DOMquerySelectorAll()
method. For better performance in modern browsers, use$( "your-pure-css-selector" ).has( selector/DOMElement )
instead.
我不怀疑在 .has()
仅用于减少匹配元素集的选择器语句中,人们可以获得更好的性能;但我怀疑测试中显示的性能消耗是通过将 .has()
检查移动到事件数据正在传递的事件处理程序中打破该约定的结果,一个新的 jQuery 对象正在构造this
,并且 .length
正在 if
语句中被访问和检查。
测试配方
为了制定测试,配置了三个事件绑定基准并应用于相同的 HTML 标记,然后是相同的事件触发测试用例——模拟用户将鼠标悬停在各种委托和非委托元素上屏幕 — 应用于三个基准中的每一个以进行比较。
基准1:
$('.foo').on('mouseenter', ':has(.other)', function(e) {
console.log(e);
});
基准2:
$('.foo').on('mouseenter', 'button:has(.other)', function(e) {
console.log(e);
});
基准3:
$('.foo').on('mouseenter', 'button', function(e) {
if ($(this).has('.other').length) {
console.log(e);
}
});
HTML:
<div class="foo">
<button type="button" id="A">some text</button>
<button type="button" id="B"><span class="other">some text</span></button>
<div id="C">some text</div>
</div>
测试用例:
$('#A').trigger('mouseenter');
$('#B').trigger('mouseenter');
$('#C').trigger('mouseenter');