JS权威指南学习笔记之文档结构和遍历
关于nodeType,其中9为Document节点(根),1为Element节点,3为Text节点,8代表Comment节点,11为DocumentFragment节点。
以下代码为实现文档遍历:
一、遍历祖先元素
1 /** 2 * 返回元素e的第N层祖先原色,如果祖先不存在或者祖先不是Element则 返回为null 3 * 如果n为0,则返回e本身,如果n省略,则置为1,返回父元素 4 * 如果n为其他,则顺利返回 5 */ 6 function parent(e, n) { 7 if (n === undefined) n = 1; 8 while(n-- && e) e = e.parentNode; 9 if (!e || e.nodeType !== 1) return null; 10 return e; 11 }
二、遍历兄弟元素
/** * 返回元素e的第n个兄弟元素 * 如果e未定义或者0,直接返回本身 * 当n为正数时,返回后续的第n个兄弟元素 * 当n为负数时,返回前面的第n个元素 */ function sibling(e,n) { while(e && n !== 0) { if (n > 0) { if (e.nextElementSibling) e = e.nextElementSibling; else { for(e=e.nextSibling; e && e.nodeType !== 1; e=e.nextSibling) } n--; } else { if (e.previousElementSibing) e = e.previousElementSibling; else { for(e=e.previousSibling; e&&e.nodeType!==1; e=e.previousSibling) } n++; } } return e; }
其中里面出现了nextElementSibling和nextSibling,他们属于不同的API,nextSibling属于节点对象树的API,包括了Element和Text对象,而nextElementSibling则属于元素对象树的API,所以当出现非Element元素时执行for(e=e.nextSibling; e && e.nodeType !== 1; e=e.nextSibling)语句。
三、遍历子孙元素
1 /** 2 * 返回e的第n个子元素 3 * 当n为负数时,从后往前计数。0为第一个,-1为倒数第一个,-2为倒数第二个,以此类推 4 */ 5 7 function child(e, n) { 8 // 当存在children数组时 9 if (e.children) { 10 if (n < 0) n += e.children.length; 11 if (n < 0) return null; // 依旧为负,则代表不存在这个子元素 12 return e.children[n]; 13 } 14 15 // 如果e没有children数组时,找到第一个子元素并向前数或者找到最后一个往前数 16 17 if (n >= 0) { // n为正,往后数 18 // 找到e的第一个元素 19 if (e.firstElementChild) e = e.firstElementChild; 20 else { 21 for(e = e.firstChild; e && e.nodeType !== 1; e = e.nextSibling) 22 /* 空循环 */; 23 } 24 return sibling(e, n); // Return the nth sibling of the first child 25 } 26 else { // n为负时,由后往前数 27 if (e.lastElementChild) e = e.lastElementChild; 28 else { 29 for(e = e.lastChild; e && e.nodeType !== 1; e=e.previousSibling) 30 /* 空循环 */; 31 } 32 return sibling(e, n+1); //+1来转化最后一个子元素为最后一个兄弟元素 33 } 34 }
浙公网安备 33010602011771号