我不禁觉得这应该更简洁(使用三个 for (...)
循环感觉不必要地昂贵),但是一种方法:
Object.prototype.classHighlight = function (over, out) {
var that = this.length ? this : [this];
function onOver() {
for (var i = 0, len = that.length; i < len; i++) {
that[i].style.backgroundColor = over;
}
}
function onOut() {
for (var i = 0, len = that.length; i < len; i++) {
that[i].style.backgroundColor = out;
}
}
for (var i = 0, len = that.length; i < len; i++) {
that[i].onmouseover = onOver;
that[i].onmouseout = onOut;
}
};
document.getElementsByClassName('test').classHighlight('#f90', '#fff');
JS 小提琴演示。
六年后,在链接到这个问题和答案之后,我正在编辑以更新上述方法,并添加片段和参考。
更新代码:
// extending the Object prototype to allow chaining of this method,
// 'over' : String, the class-name to add when the element(s) of the
// HTMLCollection/NodeList are hovered-over. We also set the default
// value of the 'over' variable in order that a class-name will always
// be present:
Object.prototype.classHighlight = function(over = 'over') {
// taking the 'this' and using the spread operator to expand
// the iterable collection to an Array:
const that = [...this],
// creating a named function to act as the event-handler for
// 'mouseenter' and 'mouseleave':
toggleHighlight = (event) => {
// iterating over the array using Array.prototype.forEach():
that.forEach(
// we're not using 'this' in here, so using an Arrow function
// to use the Element.classList API to toggle the supplied
// class on each element of the collection. If the event-type
// is exactly equal to 'mouseenter' we add the class otherwise
// we remove the class:
(el) => el.classList.toggle(over, event.type === 'mouseenter')
);
};
// iterating over the collection, again using Array.prototype.forEach():
that.forEach(
// and another Arrow function:
(element) => {
// here we bind the toggleHighlight function - created above - as
// the event-handler for both the 'mouseenter' and 'mouseleave'
// events:
element.addEventListener('mouseenter', toggleHighlight);
element.addEventListener('mouseleave', toggleHighlight);
});
};
// here we use document.getElementsByClassName() to retrieve an HTMLCollection
// of elements matching the supplied class-name; and then using chaining - which
// is why we extended the Object prototype - to pass that HTMLCollection to
// the classHighlight() function:
document.getElementsByClassName('test').classHighlight('whenOver');
.whenOver {
background-color: #f90;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
<li class="test">Something in a 'test' element</li>
</ul>
请注意,这种更新的方法,因为我们正在切换类名——而不是在元素的style
属性中添加和清除内联样式——意味着选择器的特定性可能会干扰样式的应用,例如:
// extending the Object prototype to allow chaining of this method,
// 'over' : String, the class-name to add when the element(s) of the
// HTMLCollection/NodeList are hovered-over. We also set the default
// value of the 'over' variable in order that a class-name will always
// be present:
Object.prototype.classHighlight = function(over = 'over') {
// taking the 'this' and using the spread operator to expand
// the iterable collection to an Array:
const that = [...this],
// creating a named function to act as the event-handler for
// 'mouseenter' and 'mouseleave':
toggleHighlight = (event) => {
// iterating over the array using Array.prototype.forEach():
that.forEach(
// we're not using 'this' in here, so using an Arrow function
// to use the Element.classList API to toggle the supplied
// class on each element of the collection. If the event-type
// is exactly equal to 'mouseenter' we add the class otherwise
// we remove the class:
(el) => el.classList.toggle(over, event.type === 'mouseenter')
);
};
// iterating over the collection, again using Array.prototype.forEach():
that.forEach(
// and another Arrow function:
(element) => {
// here we bind the toggleHighlight function - created above - as
// the event-handler for both the 'mouseenter' and 'mouseleave'
// events:
element.addEventListener('mouseenter', toggleHighlight);
element.addEventListener('mouseleave', toggleHighlight);
});
};
// here we use document.getElementsByClassName() to retrieve an HTMLCollection
// of elements matching the supplied class-name; and then using chaining - which
// is why we extended the Object prototype - to pass that HTMLCollection to
// the classHighlight() function:
document.getElementsByClassName('test').classHighlight('whenOver');
li.test {
background-color: fuchsia;
}
.whenOver {
background-color: #f90;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
<li class="test">Something in a 'test' element</li>
</ul>
这可以通过增加指定类名的选择器特异性来解决:
li.test {
background-color: fuchsia;
}
html body .whenOver {
background-color: #f90;
}
Object.prototype.classHighlight = function(over = 'over') {
const that = [...this],
toggleHighlight = (event) => {
that.forEach(
(el) => el.classList.toggle(over, event.type === 'mouseenter')
);
};
that.forEach(
(element) => {
element.addEventListener('mouseenter', toggleHighlight);
element.addEventListener('mouseleave', toggleHighlight);
});
};
document.getElementsByClassName('test').classHighlight('whenOver');
li.test {
background-color: fuchsia;
}
html body .whenOver {
background-color: #f90;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
<li class="test">Something in a 'test' element</li>
</ul>
或者,您可以改为使用!important
关键字来强制!important
应用该 -ified 属性,而不管具体性如何(除非另一个规则也使用!important
并且本身更具体),例如:
/* Note the ridiculous and overly-specific selector: */
html > body > ul > li.test {
background-color: fuchsia;
}
.whenOver {
/ and here, as the demo shows, !important still
wins: */
background-color: #f90 !important;
}
Object.prototype.classHighlight = function(over = 'over') {
const that = [...this],
toggleHighlight = (event) => {
that.forEach(
(el) => el.classList.toggle(over, event.type === 'mouseenter')
);
};
that.forEach(
(element) => {
element.addEventListener('mouseenter', toggleHighlight);
element.addEventListener('mouseleave', toggleHighlight);
});
};
document.getElementsByClassName('test').classHighlight('whenOver');
html > body > ul > li.test {
background-color: fuchsia;
}
.whenOver {
background-color: #f90 !important;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
<li class="test">Something in a 'test' element</li>
</ul>
但是,当涉及到!important
时,请尽量避免使用它,因为正如 MDN 所指出的:
但是,使用!important
是不好的做法,应该避免使用,因为它会破坏样式表中的自然 [级联],从而使调试变得更加困难。
“例外” ,!important
MDN。
参考: