我正在编写jQuery扩展,使用
将数据添加到DOM元素el.data('lalala', my_data);
然后使用该数据动态上传元素。
每次从服务器获取新数据时,我都需要更新所有具有
的元素el.data('lalala') != null;
为了获得所有需要的元素,我使用了James Padolsey的扩展名:
$(':data(lalala)').each(...);
一切都很好,直到我遇到需要运行该代码50次的情况 - 它非常慢!使用3640个DOM元素在我的页面上执行大约需要8秒
var x, t = (new Date).getTime();
for (n=0; n < 50; n++) {
jQuery(':data(lalala)').each(function() {
x++;
});
};
console.log(((new Date).getTime()-t)/1000);
由于我不需要RegExp作为:data
选择器的参数,我试图通过
var x, t = (new Date).getTime();
for (n=0; n < 50; n++) {
jQuery('*').each(function() {
if ($(this).data('lalala'))
x++;
});
};
console.log(((new Date).getTime()-t)/1000);
此代码更快(5秒),但我想要更多。
问有没有更快的方法来获取具有此数据密钥的所有元素?
事实上,我可以保留一个包含我需要的所有元素的数组,因为我在模块中执行.data('key')
。检查具有所需.data('lalala')
的100个元素比检查3640更好:)
所以解决方案就像
for (i in elements) {
el = elements[i];
....
但有时会从页面中删除元素(使用jQuery .remove()
)。上面描述的两个解决方案[$(':data(lalala)')
解决方案和if ($(this).data('lalala'))
]将跳过已删除的项目(我需要),而带数组的解决方案仍将指向已删除的元素(事实上,该元素不会被真正删除 - 它只会从DOM树中删除 - 因为我的数组仍然有引用。
我发现.remove()
也会从节点中删除数据,因此我的解决方案将变为
var toRemove = [];
for (vari in elements) {
var el = elements[i];
if ($(el).data('lalala'))
....
else
toRemove.push(i);
};
for (var ii in toRemove)
elements.splice(toRemove[ii], 1); // remove element from array
此解决方案快100倍!
Q 从该数组中删除时,垃圾收集器会释放DOM元素占用的内存吗?
请记住,元素已被DOM树引用,我们在数组中创建了一个新引用,然后使用.remove()
删除,然后从数组中删除。
有更好的方法吗?
答案 0 :(得分:2)
有没有更快的方法来获取具有此数据密钥的所有元素?
当然!,直接遍历数据存储而不是通过元素,例如,如果你想要计数:
var x=0;
for(var key in $.cache) {
if(typeof $.cache[key]["lalala"] != "undefined") x++;
}
这几乎是即时的,因为元素只有$.cache
的条目,如果它们有数据和/或事件,并且没有 DOM遍历发生。
对于另一篇文章,是的,这将跳过已删除的元素,因为它们的缓存也会被清除,前提是您不直接通过.innerHTML
删除它们。
答案 1 :(得分:0)
自V1.4.3起,jQuery支持HTML5-data-attribute
这意味着:如果您设置了HTML属性data-lalala
,则还可以使用element.data('lalala')
访问这些属性。这应该快得多,因为你使用了
原生属性选择器$('*[data-lalala]')
而不是一些解决方法。
所以你必须使用:
el.attr('data-lalala', my_data);
而不是
el.data('lalala', my_data);
注意:由于那些data-attributes只允许使用字符串,因此如果需要使用对象,则需要将对象存储为字符串化的JSON。