【问题标题】:getElementsByClassName in ie8 [duplicate]ie8中的getElementsByClassName [重复]
【发布时间】:2012-10-27 00:34:48
【问题描述】:

我正在尝试在 Internet Explorer 8 中为我拥有的 HTML 创建一个可折叠列表:

<li>
 <a href="#" onclick="test('node1')">hello</a>
 <ul id="node1" class="node" style="display:none">
   <li>Sub-item 1</li>
   <li>Sub-item 2</li>
 </ul>
</li>
<li>
 <a href="#" onclick="test('node2')">test</a>
  <ul id="node2" class="node" style="display:none">
   <li>Sub-item 1</li>
   <li>Sub-item 2</li>
 </ul>
</li>

在 javascript 我有

function test2(className, link) {
 var e = document.getElementsByClassName(className);

 for (var i = 0, len = e.length; i < len; i++) {
   e[i].style.display = "none";
  }

  link.innerHTML = "Expand";
 }

我用这个来称呼它:

      <a href="#" onclick="test2('node', this)">Collapse</a>

不幸的是,这种方法在 IE8 中不起作用,querySelectAll 也不起作用。有人可以提供一个如何解决此问题的示例吗?

【问题讨论】:

  • 这个问题多次返回。不知道为什么人们认为他们是第一个遇到这个问题的人?

标签: javascript html css internet-explorer-8


【解决方案1】:

IE8 不支持getElementsByClassName,但支持querySelectorAll

要使用querySelectorAll,您需要一个有效的类选择器,这意味着它需要对一个类使用Selectors API 语法,它使用. 来表示一个类。

function test2(className, link) {
    var e = document.querySelectorAll("." + className);

    for (var i = 0, len = e.length; i < len; i++) {
        e[i].style.display = "none";
    }

    link.innerHTML = "Expand";
}

【讨论】:

  • 我得到一个错误,即说不支持这个属性或方法?
  • 不知道为什么会这样。 IE8及更高版本支持。
  • 还有其他方法吗?它适用于 chrome 和 firefox,但不适用于我的 ie8
  • 看起来确实如此。在这里查看:caniuse.com/queryselector
  • @stefan — 通过包含 DOCTYPE 确保 IE 处于标准模式。如果没有 DOCTYPE,IE 会进入 quirks 模式,并且某些版本会隐藏各种 W3C DOM 方法。
【解决方案2】:

如果没有,你可以自己实现:

// shim for older browsers:
if (!document.getElementsByClassName) {
    document.getElementsByClassName = (function(){
        // Utility function to traverse the DOM:
        function traverse (node, callback) {
            callback(node);
            for (var i=0;i < node.childNodes.length; i++) {
                traverse(node.childNodes[i],callback);
            }
        }

        // Actual definition of getElementsByClassName
        return function (name) {
            var result = [];
            traverse(document.body,function(node){
                if (node.className == name) {
                    result.push(node);
                }
            });
            return result;
        }
    })()
}

现在您可以在旧版浏览器中使用document.getElementsByClassName。 shim 和本机实现之间的一个区别是 shim 返回一个真正的数组而不是 nodelist(或 htmlelementcollection)。

【讨论】:

    【解决方案3】:

    这是一个通过扩展Element.prototypedocument 的快速解决方案:

    (function() {
    if (!document.getElementsByClassName) {
        var indexOf = [].indexOf || function(prop) {
            for (var i = 0; i < this.length; i++) {
                if (this[i] === prop) return i;
            }
            return -1;
        };
        getElementsByClassName = function(className, context) {
            var elems = document.querySelectorAll ? context.querySelectorAll("." + className) : (function() {
                var all = context.getElementsByTagName("*"),
                    elements = [],
                    i = 0;
                for (; i < all.length; i++) {
                    if (all[i].className && (" " + all[i].className + " ").indexOf(" " + className + " ") > -1 && indexOf.call(elements, all[i]) === -1) elements.push(all[i]);
                }
                return elements;
            })();
            return elems;
        };
        document.getElementsByClassName = function(className) {
            return getElementsByClassName(className, document);
        };
    
        if(Element) {
            Element.prototype.getElementsByClassName = function(className) {
                return getElementsByClassName(className, this);
            };
        }
    }
    })();
    

    然而,扩展原型对象并不总是最好的主意,尤其是对于一个名称与不存在的本机函数完全一样的函数。如果你想避免原型扩展带来的问题,使用这段代码:

    (function() {
        var indexOf = [].indexOf || function(prop) {
            for (var i = 0; i < this.length; i++) {
                if (this[i] === prop) return i;
            }
            return -1;
        };
        window.getElementsByClassName = function(className,context) {
            if (context.getElementsByClassName) return context.getElementsByClassName(className);
            var elems = document.querySelectorAll ? context.querySelectorAll("." + className) : (function() {
                var all = context.getElementsByTagName("*"),
                    elements = [],
                    i = 0;
                for (; i < all.length; i++) {
                    if (all[i].className && (" " + all[i].className + " ").indexOf(" " + className + " ") > -1 && indexOf.call(elements,all[i]) === -1) elements.push(all[i]);
                }
                return elements;
            })();
            return elems;
        };
    })();​
    

    这样,您可以安全地使用接受两个参数的getElementsByClassName() 函数:

    1. className: CSS 类
    2. context: 节点

    【讨论】:

    • 这是一个很好的答案!
    • 哦,你为什么要让我在两者之间做出选择?这个决定要了我的命!
    猜你喜欢
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    相关资源
    最近更新 更多