jQuery的遍历结构设计之遍历祖先
前言:可以先自己动手做 三
,然后回头看 一、二
一、遍历归类
遍历的接口可以归为几大类:
(1)祖先
(2)同胞兄弟
(3)后代
(4)过滤
比如说 祖先的遍历接口:
有从目标节点向上遍历单个父节点的 parent();
有从目标节点向上遍历所有祖先节点的 parents();
有从目标节点向上遍历到另一目标节点的 parentsUntil()
这些遍历的接口不可能去一一实现,而是功能类似的接口,用统一的方法去封装。
- 比如针对层级关系的处理,jQuery是用 dir 方法实现的,如下所示:
// 针对层级关系的处理,jQuery就抽出了一个dir的方法,用于根据传递的元素与词素的位置关系,查找指定的元素。 // parent,parents,parentsUntil等方法如代码所示: // parents:dir(elem,"parentNode") //parentsUntil:dir(elem, "parentNode", until) function dir(elem, dir, until) { let matched = [] //parents:false let truncate = until !== undefined; //elem默认值为elem[dir] //举例: //let a=<li class="item-1">1</li> //a.parentNode=<ul class="level-2">xxx</ul> //9是Document,即整个文档的根节点 //即递归的终结条件是到document结束 while ((elem = elem[dir]) && elem.nodeType !== 9) { //1 Element即一个元素 //意思就是elem是一个Element if (elem.nodeType === 1) { //parents方法不走这边 //parentsUntil方法走这边 //body if (truncate) { //在向上递归返回父节点的同时,判断是否达到条件 //节点名和类名 if (elem.nodeName.toLowerCase() === until || elem.className === until) { break; } } matched.push(elem); } } //写法二 //elem由选择器判断,是必存在才会运行到此处的 // while (elem.nodeType !== 9) { // elem = elem[dir] // xxx // xxx // } return matched; }
二、迭代器
迭代器可以理解为一个遍历方法,
该方法的第一个参数是一个 object,该对象的每个属性都是一个 function;
该方法的第二个参数是一个 callback,该回调函数能够按顺序处理 object 的每个 function,并且不暴露 object 的内部。
这也是设计模式中的迭代器模式。
- jQuery的迭代器除了遍历外,还会将相同功能的代码合并处理:
let ajQuery = {}; //循环自定义一个对象,对象的每个属性的value是function,并在回调中对key、value进行操作 //jQuery.each即$.each //$.each(object,callback(key,value)) //$.each(array,callback(index,value)) //详情请参考:http://api.jquery.com/jquery.each/ jQuery.each({ //本质即 elem.parentNode parent: function(elem) { //调用原生js的parentNode var parent = elem.parentNode; console.log(elem,'elem87') //11表示documentFragment //documentFragment是没有父节点parentNode的!! //详情请看:深入理解DOM节点类型第四篇——文档片段节点DocumentFragment // https://www.cnblogs.com/xiaohuochai/p/5816048.html return parent && parent.nodeType !== 11 ? parent : null; }, //parents的本质即利用 elem.parentNode 向上递归直到document节点 parents: function(elem) { return dir(elem, "parentNode"); }, //该方法从父元素向上遍历 DOM 元素的祖先,直至文档根元素的所有路径,直到到达指定的元素为止 //until既可以是节点名也可以是类名 parentsUntil: function(elem, until) { return dir(elem, "parentNode", until); } }, //回调函数 //对象:key value //数组:index value function(key, value) { console.log(key,value,'name107') //将jQuery的方法定义到ajQuery上 ajQuery[key] = function(elem, until) { console.log(elem,until,'selector116') return value(elem, until); }; });
三、轮到你了
关键:
//element表示原生DOM节点$().parent
本质即elem.parentNode
$().parents
的本质即利用elem.parentNode
向上递归直到 document 节点$(). parentsUntil
的本质即elem.nodeName.toLowerCase() === 另一目标节点名 || elem.className === 另一目标节点类名
完整示例代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jQuery的遍历结构设计</title> </head> <body> <script src="jQuery.js"></script> <button id="test1">模拟遍历祖先</button> <button id="test2">jQuery遍历祖先</button> <ul class="level-1"> <li class="item-i">I</li> <li class="item-ii">II <ul class="level-2"> <li class="item-a">A</li> <li class="item-b">B <ul class="level-3"> <li class="item-1">1</li> <li class="item-2">2</li> <li class="item-3">3</li> </ul> </li> <li class="item-c">C</li> </ul> </li> <li class="item-iii">III</li> </ul> <script> // 针对层级关系的处理,jQuery就抽出了一个dir的方法,用于根据传递的元素与词素的位置关系,查找指定的元素。 // parent,parents,parentsUntil等方法如代码所示: // parents:dir(elem,"parentNode") //parentsUntil:dir(elem, "parentNode", until) function dir(elem, dir, until) { let matched = [] //parents:false let truncate = until !== undefined; //elem默认值为elem[dir] //举例: //let a=<li class="item-1">1</li> //a.parentNode=<ul class="level-2">xxx</ul> //9是Document,即整个文档的根节点 //即递归的终结条件是到document结束 while ((elem = elem[dir]) && elem.nodeType !== 9) { //1 Element即一个元素 //意思就是elem是一个Element if (elem.nodeType === 1) { //parents方法不走这边 //parentsUntil方法走这边 //body if (truncate) { //在向上递归返回父节点的同时,判断是否达到条件 //节点名和类名 if (elem.nodeName.toLowerCase() === until || elem.className === until) { break; } } matched.push(elem); } } //写法二 //elem由选择器判断,是必存在才会运行到此处的 // while (elem.nodeType !== 9) { // elem = elem[dir] // xxx // xxx // } return matched; } let ajQuery = {}; //循环自定义一个对象,对象的每个属性的value是function,并在回调中对key、value进行操作 //jQuery.each即$.each //$.each(object,callback(key,value)) //$.each(array,callback(index,value)) //详情请参考:http://api.jquery.com/jquery.each/ jQuery.each({ //本质即 elem.parentNode parent: function(elem) { //调用原生js的parentNode var parent = elem.parentNode; console.log(elem,'elem87') //11表示documentFragment //documentFragment是没有父节点parentNode的!! //详情请看:深入理解DOM节点类型第四篇——文档片段节点DocumentFragment // https://www.cnblogs.com/xiaohuochai/p/5816048.html return parent && parent.nodeType !== 11 ? parent : null; }, //parents的本质即利用 elem.parentNode 向上递归直到document节点 parents: function(elem) { return dir(elem, "parentNode"); }, //该方法从父元素向上遍历 DOM 元素的祖先,直至文档根元素的所有路径,直到到达指定的元素为止 //until既可以是节点名也可以是类名 parentsUntil: function(elem, until) { return dir(elem, "parentNode", until); } }, //回调函数 //对象:key value //数组:index value function(key, value) { console.log(key,value,'name107') //将jQuery的方法定义到ajQuery上 ajQuery[key] = function(elem, until) { console.log(elem,until,'selector116') return value(elem, until); }; }); $("#test1").click(function() { // <li class="item-1">1</li> var item = document.querySelectorAll('.item-1')[0] // console.log(item,'item93') //这他妈太神奇了。。 console.log(item['parentNode'],'item94') console.log(item['className'],'item95') console.log(item.parentNode,'item101') console.log(item.parentNode.nodeName,'item117') console.log(item.parentNode.className,'item118') console.log(ajQuery.parent(item)) console.log(ajQuery.parents(item).length) console.log(ajQuery.parentsUntil(item, 'body').length) }) $("#test2").click(function() { var item = $('.item-1') console.log(item) console.log(item.parent()[0]) console.log(item.parents().length) console.log(item.parentsUntil('body').length) }) </script> </body> </html>
github:https://github.com/AttackXiao...
(完)
相关推荐
83510998 2020-08-08
tthappyer 2020-07-25
tztzyzyz 2020-07-05
87281248 2020-07-04
82244951 2020-06-28
89510194 2020-06-27
牵手白首 2020-06-14
开心就好 2020-06-10
EdwardSiCong 2020-11-23
85477104 2020-11-17
hhanbj 2020-11-17
81427005 2020-11-11
seoppt 2020-09-13
honeyth 2020-09-13
WRITEFORSHARE 2020-09-13
84483065 2020-09-11
momode 2020-09-11