今天在课堂上,我们被赋予了一个“重新创建”jQuery功能的任务(我不知道为什么,我猜老师是虐待狂)。
我们得到以下指示:
仅使用纯javascript(甚至不是ECMEScript 2015)创建一个函数'$',它将接收标签/ id / class。
如果您只获得一个令牌[例如$(“#id)],则返回合适的元素。
如果您获得了多个令牌[例如$(“nav div div p”)] - 按层次搜索最后一个令牌。
输入: $('nav div p');
目标:获取所有p元素,这些元素的div位于div之上,其导航位于div之上。
if (query.split(" ").length > 1) {
var first = query.split(" ")[0];
var rest = query.split(" ").slice(1);
var curr_elements;
if (first.match(/^#.*/i)) {
curr_elements = (document.getElementById(first.substring(1)));
} else if (query.match(/^\..*/i)) {
curr_elements = document.getElementsByClassName(first.substring(1));
} else if (query.match(/^\w.*/i)) {
curr_elements = document.getElementsByTagName(first);
}
curr_elements = [].slice.call(curr_elements);
for (var e = 0; e < curr_elements.length; e++) {
if (curr_elements[e].hasChildNodes()) {
for (var i = 0; i < rest.length; i++) {
var temp = rest[i];
var children;
if (temp.match(/^#.*/i)) {
children = (document.getElementById(temp.substring(1)));
} else if (temp.match(/^\..*/i)) {
children = document.getElementsByClassName(temp.substring(1));
} else if (temp.match(/^\w.*/i)) {
children = document.getElementsByTagName(temp);
}
alert(children);
//curr_elements += children;
}
}
}
this.elements = curr_elements;
} else {
if (query.match(/^#.*/i)) {
this.elements.push(document.getElementById(query.substring(1)));
} else if (query.match(/^\..*/i)) {
this.elements = document.getElementsByClassName(query.substring(1));
} else if (query.match(/^\w.*/i)) {
this.elements = document.getElementsByTagName(query);
}
}
<nav>
<p id="1"></p>
</nav>
<nav>
<div>
</div>
<p>
<div>
<p id=2></p>
</div>
</p>
</nav>
<nav>
<div>
<p id="3"></p>
<p id="4"></p>
<div>
</div>
</div>
</nav>
<nav>
<div>
<div>
<div>
<p id="5"></p>
</div>
</div>
</div>
</nav>
查询:第一个arg是标签/ ID /类名
curr_elements:数组,用于临时存储我得到的元素
this.elements:最终的HTMLCollection。
与单个令牌($(“p”);)相关的部分工作正常,但我无法弄清楚如何递归/迭代元素以获得段落。
希望得到某人关于如何继续的想法/建议。
答案 0 :(得分:1)
您的代码非常可靠,您只是不使用递归,在这种情况下非常有用。
我已将代码更改为使用递归方法:
function $(selector, context) {
if (!selector) return false;
// context should be an array of previous nodes we have found. If it's undefined, assume the single-item array [document] as the starting context
if (!context) context = [document];
var s = selector.split(" ");
var first = s.shift();
var curr_elements = [], els;
for (var i=0; i < context.length; i++) {
var c = context[i];
// make sure els gets converted into a real array of nodes
if (first.match(/^#.*/i)) {
els = [c.getElementById(first.substring(1))];
} else if (first.match(/^\..*/i)) {
els = [].slice.call(c.getElementsByClassName(first.substring(1)));
} else if (first.match(/^\w.*/i)) {
els = [].slice.call(c.getElementsByTagName(first));
}
curr_elements = curr_elements.concat(els);
}
// if there are more items in s, then curr_elements is the context in which to find them. Otherwise, curr_elements is the array of elements we were looking for.
if (s.length) return $(s.join(" "), curr_elements);
return curr_elements;
}
var a = $(".test span");
console.log(a);
<div class="test">
<span>1</span><span>2</span><span>3</span>
</div>
<div class="not_test">
<span>4</span><span>5</span><span>6</span>
</div>
<p class="test">
<span>7</span><span>8</span><span>9</span>
</p>