我试图从我的页面中删除jquery并将一些功能重写为纯js。 有2个列表与类工作,包含很少的li元素。每个li元素都应该有一个单击动作来添加class' active'它。在jquery中它非常简单:
$('.work li').on('click', function () {
var that = $(this);
that.parent().find('li.active').removeClass('active');
$(this).addClass('active');
})
纯js中是否有更好的解决方案,而不是使用嵌套循环制作类似的东西:
var lists = document.getElementsByClassName('work');
for(var i=0; i<lists.length; i++){
var children = lists[i].querySelectorAll('li');
for(var j=0; j<children.length;j++){
children[j].addEventListener();
}
}
答案 0 :(得分:5)
有两个包含类工作的列表,包含很少的li元素。每个李 element应该在click上有一个动作,将类'active'添加到它。
您可以通过向li
返回的所有querySelectorAll
添加事件侦听器来创建整个功能。 querySelectorAll
返回一个nodeList而不是一个数组,因此需要映射它以便迭代它。但请注意,我们仍在迭代该集合。
示例代码段 :
var lists = document.querySelectorAll(".work li"),
doSomething = function() {
[].map.call(lists, function(elem) { elem.classList.remove("active") });
this.classList.add("active");
};
[].map.call(lists, function(elem) {
elem.addEventListener("click", doSomething, false);
});
li { cursor: pointer; }
.active { background-color: yellow; }
<ul class="work"><li>One</li><li>Two</li><li>Three</li></ul>
<ul class="work"><li>Four</li><li>Five</li><li>Six</li></ul>
实际上,您也可以使用事件委派并仅在ul
上添加事件侦听器,然后使用event.target
来处理您的例程。这比为每个li
添加一个事件监听器更好,以防它们有很多。只有ul
的处理程序。
在纯粹的js中是否有更好的解决方案,而不是制作类似的东西 这与嵌套循环
不是真的。无论如何,你必须迭代这组元素。在爵士方面更好,是的。在避免循环方面更好,没有。在效率方面更好,是的。将上述vanilla javascript代码与您问题中的jQuery代码进行比较:
$('.work li').on('click', function () { // internally will iterate and add listener to each li
var that = $(this);
that.parent().find('li.active').removeClass('active'); // go to parent and then find li
$(this).addClass('active');
});
答案 1 :(得分:3)
您实际上可以在包装器元素上附加Click事件侦听器,并使用li
(或对于IE event.target
)过滤掉单击的event.srcElement
元素。
尝试下面的代码段(不是生产代码,它应该增强,特别是对于浏览器兼容性)。这个解决方案的好处是你不必注意动态添加到包装元素的新元素...
function clickHandler(e) {
var elem, evt = e ? e : event;
if (evt.srcElement) {
elem = evt.srcElement;
} else if (evt.target) {
elem = evt.target;
}
// Filter out li tags
if (elem && ('LI' !== elem.tagName.toUpperCase())) {
return true;
}
console.log('You clicked: ' + elem.innerHTML)
return true;
}
var lists = document.getElementsByClassName('work');
for (var i = 0; i < lists.length; i++) {
var children = lists[i].addEventListener('click', clickHandler);
}
&#13;
<ul class="work">
<li>1.1</li>
<li>1.2</li>
<li>1.3</li>
<li>1.4</li>
</ul>
<ul class="work">
<li>2.1</li>
<li>2.2</li>
<li>2.3</li>
<li>2.4</li>
</ul>
<ul class="work">
<li>3.1</li>
<li>3.2</li>
<li>3.3</li>
<li>3.4</li>
</ul>
&#13;
答案 2 :(得分:2)
不确定。为什么不更好地利用document.querySelectorAll
?它确实使用了css的语法,因此我们可以一次抓取它们。
也许是这样的:
{
liList = document.querySelectorAll('.work li');
var i, n = liList.length;
for (i=0; i<n; i++)
liList[i].addEventListener(eventName, functionName, useCapture);
}
答案 3 :(得分:2)
querySelectorAll()是非常强大的工具。
我为你做了JSFiddle。
代码仍然足够好看和可读:
for (var item of document.querySelectorAll(".work li")) {
item.addEventListener("click", function (evt) {
evt.target.classList.add("active");
}, false);
}
另一种方法是(如果您仍想使用forEach进行迭代):
Array.prototype.forEach.call(document.querySelectorAll(".work li"), function(item) {
item.addEventListener("click", function (evt) {
evt.target.classList.add("active");
}, false);
});
此处(JSFiddle)我们通过querySelectorAll(".work li")
按NodeList calling方法对Array.prototype.forEach进行了整理。
这里(Jsfiddle)是完整的例子,可以切换类:
Array.prototype.forEach.call(document.querySelectorAll(".work li"), function(item) {
item.addEventListener("click", function (evt) {
evt.target.toggleActive = !evt.target.toggleActive;
evt.target.classList[!!evt.target.toggleActive ? 'add' : 'remove']("active");
}, false);
});
最后,如果一次只有一个活动元素(Jsfiddle):
var currentActiveElement;
Array.prototype.forEach.call(document.querySelectorAll('.work li'), function(item) {
item.addEventListener('click', function(evt) {
currentActiveElement && currentActiveElement.classList.remove('active');
currentActiveElement = evt.target;
currentActiveElement.classList.add('active');
}, false);
});
答案 4 :(得分:1)
人们抱怨使用原生DOM方法的冗长,但没有问题,一些战略性的糖无法帮助。首先写下你喜欢的方式:
eachClass('work', function(work) {
eachSelector(work, 'li', function(li) {
on(li, 'click', function() {
eachChild(parent(li), active.remove);
active.add(li);
});
});
});
现在您只需撰写eachClass
,eachSelector
,eachChild
,parent
和on
,如下所示。他们每人约2-3行。你只需要写一次,瞧,你有自己的小库。
function eachClass(cls, fn) {
[].forEach.call(document.getElementsByClassName(cls), fn);
}
什么是active
?它是我们可以创建的用于设置和删除特定类的小对象:
function makeClassSetter(cls) {
return {
add: function(elt) { elt.classList.add(cls); },
remove: function(elt) {elt.classList.remove(cls); }
};
}
var active = makeClassSetter('active');
等等。优秀的程序员不断构建小框架和层,实用程序和迷你语言。这就是使他们的代码紧凑,可读,减少错误并且更容易编写的原因。
答案 5 :(得分:0)
我也一直在寻找简洁但有用的解决方案。
这是我想出的最好方法:
tag = document.querySelectorAll('.tag');
tag.forEach(element => {
element.addEventListener("mouseover", aFunction);
});
function aFunction(){
this.style.background = "grey";
}
querySelectorAll是一个功能强大的方法,当存在用例时,foreach总是更短并且更易于使用。 我更喜欢给函数命名并添加它们,尽管我想如果愿意的话,您可以轻松地用foreach中的另一个箭头函数替换它