之前我在也谈数组去重中介绍了普通的数组去除重复的元素,在选择器的开发过程中,会碰到这样的需求,就是删除一组DOM数组中重复的元素,使用之前的方法肯定行不通,对于 DOM 数组去重,需要另外的处理办法。什么情况下会选取重复的 DOM 元素?下面是一个比较常见的情况,先看 HTML 结构:
<ul>
<li>test1</li>
<li>test2</li>
<li>test3
<ul>
<li>测试1</li>
<li>测试2</li>
</ul>
</li>
</ul>
如果是这样的选择器:query( "ul li" ),按照从左到右的查找顺序,会先得到所有 ul 的集合。
[ ul, ul ]
得到了所有 ul 的集合,继续使用 getElementsByTagName 来查找 li,那么第1个 ul 元素就会查找到所有的 li 元素,接下来第2个也会查找到2个 li 元素,最后2个 li 元素就是重复的。这样的情况下,用常规的去重办法要将查找到的所有的 li 元素进行遍历,然后再排序,最后再过滤,这种方法稍后再说。
先来看看上面的 ul 的集合,两个元素之间是否存在关系呢?第1个 ul 是第2个 ul 的父元素,那么第1个 ul 就包含了第2个 ul。
// 检测a元素是否包含了b元素
var contains = function( a, b ){
// 标准浏览器支持compareDocumentPosition
if( a.compareDocumentPosition ){
return !!( a.compareDocumentPosition(b) & 16 );
}
// IE支持contains
else if( a.contains ){
return a !== b && a.contains( b );
}
return false;
};
上面的函数就是检测某元素是否被另一个元素包含,利用这个函数,那么在使用 getElementsByTagName 查找子元素的时候只需要查找第1个 ul 的所有 li 元素即可,这样就可以避免查找重复的元素。
如果无法检测相邻 DOM 数组元素间是否存在包含关系,那么就要先对数组先进行排序,然后再删除重复的元素。
var hasDuplicate = false, // 是否有重复的DOM元素
distinct = function( nodelist ){
// 对于标准浏览器的处理
var k = 1;
// 先用自定义的sort函数对数组进行排序
nodelist.sort(function( a, b ){
if( a === b ){
hasDuplicate = true;
return 0;
}
return a.compareDocumentPosition(b) & 4 ? -1 : 1;
});
// 如果存在重复的数组元素使用splice进行删除
if( hasDuplicate ){
for( ; k < nodelist.length; k ){
elem = nodelist[k];
if( elem === nodelist[k - 1] ){
nodelist.splice( k--, 1 );
}
}
}
return nodelist;
};
对于IE,IE支持 sourceIndex,但不支持 compareDocumentPosition 方法,利用 sourceIndex,可以大大的优化排序的算法。
新建一个空对象A和空数组B ,将元素的 sourceIndex 属性取出作为空对象A的键(key),使用 new String 创建一个对象C,将 DOM 元素存放到该C对象中,再将该对象C存放到空数组B中,遍历 DOM 数组的时候检测A中是否已经存在相同的键(key)。然后再对数组B进行sort排序,这样避免了直接对 DOM 元素进行 sort 排序,而是对 sourceIndex 进行排序,排序完后再取出数组B中存放的 DOM 元素。那么最终的代码如下:
buy cigarettes
var hasDuplicate = false, // 是否有重复的DOM元素
distinct = function( nodelist ){
if( nodelist.length < 2 ){
return nodelist;
}
var i http://www.phpaide.com/?langue=en = 0,
k = 1,
len = nodelist.length;
// IE的DOM元素都支持sourceIndex
if( nodelist[0].sourceIndex ){
var arr = [],
obj = {},
elems = [],
j = 0,
index, elem;
for( ; i < len; i ){
elem = nodelist[i];
index = elem.sourceIndex 1e8;
if( !obj[index] ){
// 使用 new String 创建一个对象 C,
// 将 DOM 元素存放到该 C 对象中,
// 再将该对象 C 存放到空数组 B 中
( arr[j ] = new String(index) ).elem = elem;
// 将 sourceIndex 属性取出作为空对象 A 的键(key)
obj[index] = true;
}
}
arr.sort();
// 取出存放在数组C中的DOM元素
while( j ){
elems[--j] = arr[j].elem;
}
arr = null;
return elems;
}
// 标准浏览器的DOM元素都支持compareDocumentPosition
else{
// 先用自定义的sort函数对数组进行排序
nodelist.sort(function( a, b ){
if( a === b ){
hasDuplicate = true;
return 0;
}
return a.compareDocumentPosition(b) & 4 ? -1 : 1;
});
// 如果存在重复的数组元素使用splice进行删除
if( hasDuplicate ){
for( ; k < nodelist.length; k ){
elem = nodelist[k];
if( elem === nodelist[k - 1] ){
nodelist.splice( k--, 1 );
}
}
}
return nodelist;
}
};
将上面的代码稍微变动下,就可以增加一个功能,检测一组 DOM 数组中是否存在同级元素,然后删除同级元素,只要将 elem 替换成 elem.parentNode 即可。这个功能在选择器的开发中也非常有用,这里就不贴重复的代码了。
参考:
zp8497586rq
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8