使用 JavaScript 添加类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17944843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 10:11:48  来源:igfitidea点击:

add class with JavaScript

javascriptclass

提问by vincentieo

I am writing some vanilla JavaScript to create a nice navigation menu. I am stuck on adding an active class.

我正在编写一些普通的 JavaScript 来创建一个漂亮的导航菜单。我坚持添加一个活动类。

I am getting elements by class name NOT by id. The below code works if substituted with id, however, I need it to apply to more than one element.

我按类名而不是 id 获取元素。如果用 id 代替,下面的代码有效,但是,我需要将它应用于多个元素。

HTML

HTML

<img class="navButton" id="topArrow" src="images/arrows/top.png" />
<img class="navButton" id="rightArrow" src="images/arrows/right.png" />

JS

JS

var button = document.getElementsByClassName("navButton");

button.onmouseover = function() {
    button.setAttribute("class", "active");
    button.setAttribute("src", "images/arrows/top_o.png");
}

No answers containing jQuery please.

请没有包含 jQuery 的答案。

回答by mohkhan

document.getElementsByClassNamereturns a node list. So you'll have to iterate over the list and bind the event to individual elements. Like this...

document.getElementsByClassName返回一个节点列表。因此,您必须遍历列表并将事件绑定到单个元素。像这样...

var buttons = document.getElementsByClassName("navButton");

for(var i = 0; i < buttons.length; ++i){
    buttons[i].onmouseover = function() {
        this.setAttribute("class", "active");
        this.setAttribute("src", "images/arrows/top_o.png");
    }
}

回答by Elias Van Ootegem

In your snippet, buttonis an instance of NodeList, to which you can't attach an event listener directly, nor can you change the elements' classNameproperties directly.
Your best bet is to delegate the event:

在您的代码段中,button是 的一个实例NodeList,您不能直接将事件侦听器附加到该实例,也不能直接更改元素的className属性。
最好的办法是委托事件:

document.body.addEventListener('mouseover',function(e)
{
    e = e || window.event;
    var target = e.target || e.srcElement;
    if (target.tagName.toLowerCase() === 'img' && target.className.match(/\bnavButton\b/))
    {
        target.className += ' active';//set class
    }
},false);

Of course, my guess is that the activeclass needs to be removed once the mouseoutevent fires, you might consider using a second delegator for that, but you couldjust aswell attach an event handler to the one element that has the activeclass:

当然,我的猜测是active一旦mouseout事件触发就需要删除该类,您可能会考虑为此使用第二个委托人,但您也可以将事件处理程序附加到具有active该类的一个元素:

document.body.addEventListener('mouseover',function(e)
{
    e = e || window.event;
    var oldSrc, target = e.target || e.srcElement;
    if (target.tagName.toLowerCase() === 'img' && target.className.match(/\bnavButton\b/))
    {
        target.className += ' active';//set class
        oldSrc = target.getAttribute('src');
        target.setAttribute('src', 'images/arrows/top_o.png');
        target.onmouseout = function()
        {
            target.onmouseout = null;//remove this event handler, we don't need it anymore
            target.className = target.className.replace(/\bactive\b/,'').trim();
            target.setAttribute('src', oldSrc);
        };
    }
},false);

There is some room for improvements, with this code, but I'm not going to have all the fun here ;-).

这段代码还有一些改进的空间,但我不会在这里享受所有的乐趣;-)。

Check the fiddle here

检查小提琴here

回答by Aleksandr Albert

Here is a method adapted from Jquery 2.1.1 that take a dom element instead of a jquery object (so jquery is not needed). Includes type checks and regex expressions:

这是一种改编自 Jquery 2.1.1 的方法,它采用 dom 元素而不是 jquery 对象(因此不需要 jquery)。包括类型检查和正则表达式:

function addClass(element, value) {
    // Regex terms
    var rclass = /[\t\r\n\f]/g,
        rnotwhite = (/\S+/g);

    var classes,
        cur,
        curClass,
        finalValue,
        proceed = typeof value === "string" && value;

    if (!proceed) return element;

    classes = (value || "").match(rnotwhite) || [];

    cur = element.nodeType === 1
        && (element.className
                ? (" " + element.className + " ").replace(rclass, " ")
                : " "
        );

    if (!cur) return element;

    var j = 0;

    while ((curClass = classes[j++])) {

        if (cur.indexOf(" " + curClass + " ") < 0) {

            cur += curClass + " ";

        }

    }

    // only assign if different to avoid unneeded rendering.
    finalValue = cur.trim();

    if (element.className !== finalValue) {

        element.className = finalValue;

    }

    return element;
};

回答by Yoni

Simply add a class name to the beginning of the funciton and the 2nd and 3rd arguments are optional and the magic is done for you!

只需在函数的开头添加一个类名,第二个和第三个参数是可选的,魔术就为您完成了!

function getElementsByClass(searchClass, node, tag) {

  var classElements = new Array();

  if (node == null)

    node = document;

  if (tag == null)

    tag = '*';

  var els = node.getElementsByTagName(tag);

  var elsLen = els.length;

  var pattern = new RegExp('(^|\\s)' + searchClass + '(\\s|$)');

  for (i = 0, j = 0; i < elsLen; i++) {

    if (pattern.test(els[i].className)) {

      classElements[j] = els[i];

      j++;

    }

  }

  return classElements;

}

回答by ketan

There is build in forEach loop for array in ECMAScript 5th Edition.

在 ECMAScript 第 5 版中为数组内置了 forEach 循环。

var buttons = document.getElementsByClassName("navButton");

Array.prototype.forEach.call(buttons,function(button) { 
    button.setAttribute("class", "active");
    button.setAttribute("src", "images/arrows/top_o.png"); 
});

回答by ojrask

I like to use a custom "foreach" function of sorts for these kinds of things:

我喜欢使用自定义的“foreach”函数来处理这些事情:

function Each( objs, func )
{
    if ( objs.length ) for ( var i = 0, ol = objs.length, v = objs[ 0 ]; i < ol && func( v, i ) !== false; v = objs[ ++i ] );
    else for ( var p in objs ) if ( func( objs[ p ], p ) === false ) break;
}

(Can't remember where I found the above function, but it has been quite useful.)

(不记得我在哪里找到了上述功能,但它非常有用。)

Then after fetching your objects (to elementsin this example) just do

然后在获取你的对象(elements在这个例子中)之后就做

Each( elements, function( element )
{
    element.addEventListener( "mouseover", function()
    {
        element.classList.add( "active" );
        //element.setAttribute( "class", "active" );
        element.setAttribute( "src", "newsource" );
    });

    // Remove class and new src after "mouseover" ends, if you wish.
    element.addEventListener( "mouseout", function()
    {
        element.classList.remove( "active" );
        element.setAttribute( "src", "originalsource" );
    });
});

classListis a simple way for handling elements' classes. Just needs a shim for a few browsers. If you must use setAttributeyou must remember that whatever is set with it willoverwrite the previous values.

classList是一种处理元素类的简单方法。只需要一些浏览器的垫片。如果您必须使用,setAttribute您必须记住,用它设置的任何内容都会覆盖以前的值。

EDIT: Forgot to mention that you need to use attachEventinstead of addEventListeneron some IE versions. Test with if ( document.addEventListener ) {...}.

编辑:忘记提及您需要在某些 IE 版本上使用attachEvent而不是使用addEventListener。用 测试if ( document.addEventListener ) {...}

回答by Arda

getElementsByClassName()returns HTMLCollection so you could try this

getElementsByClassName()返回 HTMLCollection 所以你可以试试这个

var button = document.getElementsByClassName("navButton")[0];

Edit

编辑

var buttons = document.getElementsByClassName("navButton");
for(i=0;buttons.length;i++){
   buttons[i].onmouseover = function(){
     this.className += ' active' //add class
     this.setAttribute("src", "images/arrows/top_o.png");
   }
}