【问题标题】:Get All Elements By ClassName and Change ClassName通过 ClassName 获取所有元素并更改 ClassName
【发布时间】:2014-03-20 05:29:26
【问题描述】:

我想...

  1. 扫描文档以查找具有特定类名的所有元素
  2. 在该元素的 innerHTML 上执行一些关键功能
  3. 更改该元素的类名,以便以后再扫描时不会重做该元素

我认为这段代码可以工作,但由于某种原因,它在第一个实例之后中断了循环,并且元素的类名永远不会改变。请不要使用框架。

function example()
{
    var elementArray;

    elementArray = document.getElementsByClassName("exampleClass");

    for(var i = 0; i < elementArray.length; i++)
    {
        // PERFORM STUFF ON THE ELEMENT
        elementArray[i].setAttribute("class", "exampleClassComplete");
        alert(elementArray[i].className);
    }   
}

编辑(最终答案) -- 这是最终产品以及我如何在我的站点中实施 @cHao 的解决方案。目标是获取页面上的各种时间戳并将它们更改为时间之前。谢谢大家的帮助,我从这个问题中学到了很多东西。

function setAllTimeAgos()
{
    var timestampArray = document.getElementsByClassName("timeAgo");

    for(var i = (timestampArray.length - 1); i >= 0; i--)
    {
        timestampArray[i].innerHTML = getTimeAgo(timestampArray[i].innerHTML);
        timestampArray[i].className = "timeAgoComplete";
    }
}

【问题讨论】:

  • 为什么这个问题应该得到-1,因为用户不想使用jquery或任何其他框架?向我 +1,因为他们没有。
  • 当你想为外部网站构建插件时,使用jquery是不安全的,它可以改变其他页面脚本
  • 请不要回答问题中的问题。用答案添加新答案。

标签: javascript


【解决方案1】:

问题在于返回给您的 NodeList 是“实时的”——它会随着您更改类名而改变。也就是说,当您更改第一个元素的类时,列表立即比原来短一个元素。

试试这个:

  while (elementArray.length) {
    elementArray[0].className = "exampleClassComplete";
  }

(无需使用setAttribute() 来设置“class”值 - 只需更新“className”属性即可。在旧版本的IE 中使用setAttribute() 无论如何都行不通。)

或者,将您的 NodeList 转换为普通数组,然后使用您的索引迭代:

  elementArray = [].slice.call(elementArray, 0);
  for (var i = 0; i < elementArray.length; ++i)
    elementArray[i].className = "whatever";

正如评论中所指出的,这样做的优点是不依赖 NodeList 对象的语义。 (还要注意,再次感谢评论,如果您需要它在旧版本的 Internet Explorer 中工作,您必须编写一个显式循环来将元素引用从 NodeList 复制到数组。)

【讨论】:

  • 我不建议将while (elementArray.length) { 作为条件。它不像一个数组,它只是读取缓存的属性。 .length 的每次获取都需要查看 DOM 以查看有多少匹配的元素。此外,如果在 IE8 中为 gEBCN 使用 shim,则会出现无限循环,因为列表不会生效。
  • 所以第二次我更改了类名,该元素是从列表中获取的。那是精神错乱!到时会接受。感谢您的帮助。
  • 不要吹毛求疵,但你的 .slice() 在 IE8 和更低版本中会失败,因为 elementArray 是一个主机对象。 IMO,我只是做一个反向迭代。它对实时和非实时列表的工作方式相同,并且与浏览器兼容且速度快。
  • @squint 是的,你是对的!哇,我很高兴我现在不必经常弄乱 IE :-)
  • @gmustudent:也不例外。这只是通向同一方法的不同路径。
【解决方案2】:

大多数返回元素列表的 DOM 函数返回的是 NodeList 而不是数组。最大的不同是 NodeList 通常是live,这意味着更改文档会导致节点神奇地出现或消失。这可能会导致节点移动一点,并抛出一个不考虑它的循环。

不过,您可以简单地在返回的列表上向后循环,而不是将列表转换为数组或其他任何东西。

function example()
{
    var elements = document.getElementsByClassName("exampleClass");

    for(var i = elements.length - 1; i >= 0; --i)
    {
        // PERFORM STUFF ON THE ELEMENT
        elements[i].className = "exampleClassComplete";

        // elements[i] no longer exists past this point, in most browsers
    }   
}

此时 NodeList 的活跃度无关紧要,因为从中删除的唯一元素将是您当前所在的元素之后。之前出现的节点不受影响。

【讨论】:

  • +1 用于反向循环,如 @Pointy 答案的 cmets 中所述
  • @Xotic750:当我之前遇到这个问题时,这对我来说似乎是自然的解决方案。当我查看答案并注意到大多数人都在用数组放屁时......我不得不插话。:)
  • 是的,一个非常简单的解决方案来更改活动节点列表,您的更改可能会影响列表:)
【解决方案3】:

另一种方法是使用选择器:

var arr = document.querySelectorAll('.exampleClass');
for (var i=0;i<arr.length;i++) {
    arr.innerHTML = "new value";
}

虽然它与旧版浏览器不兼容,但如果网页内容适用于现代浏览器,它也可以解决问题。

【讨论】:

  • 有人建议但仅作为@Pointy 答案下的评论
  • 哦,刚刚看到了。我将删除“不建议”;-)
【解决方案4】:

你也可以,使用 2 个数组,将数据推入第一个数组,然后做你需要做的事情[比如改变元素的类]:

function example()
{
    var elementArray=[];
    var elementsToBeChanged=[];
    var i=0;

    elementArray = document.getElementsByClassName("exampleClass");

    for( i = 0; i < elementArray.length; i++){
        elementsToBeChanged.push(elementArray[i]);
    }

    for( i=0; i< elementsToBeChanged.length; i++)
    {
        elementsToBeChanged[i].setAttribute("class", "exampleClassComplete");
    }
}

【讨论】:

    【解决方案5】:

    另一种可能性,也应该是跨浏览器,使用手工定制的 getElementsByClassName,它将固定节点列表作为数组返回。这应该支持 IE5.5 及更高版本。

    function getElementsByClassName(node, className) {
        var array = [],
            regex = new RegExp("(^| )" + className + "( |$)"),
            elements = node.getElementsByTagName("*"),
            length = elements.length,
            i = 0,
            element;
    
        while (i < length) {
            element = elements[i];
            if (regex.test(element.className)) {
                array.push(element);
            }
    
            i += 1;
        }
    
        return array;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-10
      • 2019-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-10
      相关资源
      最近更新 更多