遍历的接口我们可以归为几大类:
1 祖先 2 同胞兄弟 3 后代 4 过滤
遍历的接口很多都是具有相似或者说是一类的处理功能,那么这种接口的设计我们不能就事论事的一个一个去实现,这样代码就会显得非常累赘也不容易维护,那么就这么几大类Query分了好几十API出来,丰富的接口可以让高层的设计更为简单。但是框架内部的却要简练。那么针对这种类似功能的接口,jQuery内部就会做更多的抽象处理了。
1.针对层级关系的处理,jQuery就抽出了一个dir的方法,用于根据传递的元素与词素的位置关系,查找指定的元素。
parent,parents,parentsUntil等方法如代码所示:
function dir(elem, dir, until) { //参考右边代码 return matched; }
2.我们在上半部的第一章中就提到过迭代器,迭代器是一个框架的重要设计。
我们经常需要提供一种方法顺序的用来处理聚合对象中各个元素,而又不暴露该对象的内部,这也是设计模式中的迭代器模式。
迭代器除了单纯的遍历,在jQuery内部的运用最多的就是接口的抽象合并,相同功能的代码功能合并处理:
jQuery.each({ parent: function(elem) {}, parents: function(elem) {}, nextAll: function(elem) {}, prevAll: function(elem) {}, ................ }, function(name, fn) { api[name] = function(until, selector){ //代码右图 }; });
可以看出上面代码方法,针对相同的功能,节约了大量的代码空间。
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script src="http://img1.sycdn.imooc.com//down/540812440001e40e00000000.js" type="text/javascript"></script> <title></title> </head> <body> <button id="test1">jQuery遍历祖先</button> <button id="test2">模拟遍历祖先</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 type="text/javascript"> var ajQuery = {}; function dir(elem, dir, until) { var matched = [], truncate = until !== undefined; while ((elem = elem[dir]) && elem.nodeType !== 9) { if (elem.nodeType === 1) { if (truncate) { if (elem.nodeName.toLowerCase() == until || elem.className == until) { break; } } matched.push(elem); } } return matched; } jQuery.each({ parent: function(elem) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function(elem) { return dir(elem, "parentNode"); }, parentsUntil: function(elem, until) { return dir(elem, "parentNode", until); } }, function(name, fn) { ajQuery[name] = function(until, selector) { return fn(until, selector); }; }); $("#test1").click(function() { var item = $('.item-1'); alert(item.parent()[0]) alert(item.parents().length) alert(item.parentsUntil('body').length) }) $("#test2").click(function() { var item = document.querySelectorAll('.item-1')[0] alert(ajQuery.parent(item)) alert(ajQuery.parents(item).length) alert(ajQuery.parentsUntil(item, 'body').length) }) </script> </body> </html>