带有 classList 的代码在 IE 中不起作用?

IT技术 javascript internet-explorer
2021-01-23 14:58:22

我正在使用以下代码,但在 IE 中失败。消息是:

无法获取属性“添加”的值:对象为空或未定义”

我认为这只是 IE 支持问题。您将如何使以下代码在 IE 中工作?

有任何想法吗?

var img = new Image();
img.src = '/image/file.png';
img.title = 'this is a title';
img.classList.add("profilePic");
var div = document.createElement("div");
div.classList.add("picWindow");
div.appendChild(img);
content.appendChild(div);
6个回答

classListIE9 及更低版本不支持属性。不过 IE10+ 支持它。
使用className += " .."来代替。注意:不要省略空格:类名应添加在以空格分隔的列表中。

var img = new Image();
img.src = '/image/file.png';
img.title = 'this is a title';
img.className += " profilePic"; // Add profilePic class to the image

var div = document.createElement("div");
div.className += " picWindow";  // Add picWindow class to the div
div.appendChild(img);
content.appendChild(div);
IE11 在 classList 上仍然存在错误,它不支持 SVG 元素上的 classList。
2021-03-21 14:58:22
并且 jQuery 也不能向 SVG 元素添加类,因此如果您想操作 SVG,上面的解决方案看起来是唯一可能的事情。
2021-03-25 14:58:22
在严格模式下,这会产生错误,因为 className 是只读的。
2021-03-26 14:58:22
@JasonAller 这极不可能,classNameDOM 元素属性是读写。
2021-03-31 14:58:22
@MikeChristensen 该className属性始终存在。它被初始化为一个空字符串。为了便于代码维护,推荐使用+=来添加类名。
2021-04-07 14:58:22

正如其他人所提到的,classListIE9 及更早版本不支持。除了上面 Alex 的替代方案外,还有一些 polyfills 旨在成为替代品,即只需将这些包含在您的页面中,IE 就可以正常工作(著名的遗言!)。

https://github.com/eligrey/classList.js/blob/master/classList.js

https://gist.github.com/devongovett/1381839

@BradAdams在这里这里Caniuse 和 MDN 也有报道。不过,所有这些问题都已在 Microsoft Edge 中解决!
2021-03-18 14:58:22
我正在使用 IE 11 并且 classList 似乎不起作用(适用于 chrome)
2021-03-21 14:58:22
@johnktejik 如果您一次添加或删除多个类,它将无法在 IE11、Firefox 24- 和 Chrome 24- 中工作。那是你在做的吗?
2021-03-23 14:58:22
这很奇怪 - caniuse.com 说 IE10+ 应该支持它。我建议在 Twitter 上询问 @TheWebJustWorks 或在webcompat.com上提交问题
2021-03-30 14:58:22
SVG 元素仍然不支持 classList,这些 polyfill 可以解决问题
2021-04-04 14:58:22

在 IE 10 和 11 中,classList 属性定义在 HTMLElement.prototype 上。

为了让它在 SVG 元素上工作,应该在 Element.prototype 上定义该属性,就像在其他浏览器上一样。

一个非常小的修复是将确切的 propertyDescriptor 从 HTMLElement.prototype 复制到 Element.prototype:

if (!Object.getOwnPropertyDescriptor(Element.prototype,'classList')){
    if (HTMLElement&&Object.getOwnPropertyDescriptor(HTMLElement.prototype,'classList')){
        Object.defineProperty(Element.prototype,'classList',Object.getOwnPropertyDescriptor(HTMLElement.prototype,'classList'));
    }
}
  • 我们需要复制描述符,因为Element.prototype.classList = HTMLElement.prototype.classList会抛出Invalid calling object
  • 第一项检查可防止在本机支持的浏览器上覆盖该属性。
  • 第二个检查是防止在 9 之前的 IE 版本上出现错误,其中尚未实现 HTMLElement,以及在未实现 classList 的 IE9 上。

对于 IE 8 & 9,使用以下代码,我还为 Array.prototype.indexOf 包含了一个(缩小的)polyfill,因为 IE 8 本身不支持它(polyfill 来源:Array.prototype.indexOf

//Polyfill Array.prototype.indexOf
Array.prototype.indexOf||(Array.prototype.indexOf=function (value,startIndex){'use strict';if (this==null)throw new TypeError('array.prototype.indexOf called on null or undefined');var o=Object(this),l=o.length>>>0;if(l===0)return -1;var n=startIndex|0,k=Math.max(n>=0?n:l-Math.abs(n),0)-1;function sameOrNaN(a,b){return a===b||(typeof a==='number'&&typeof b==='number'&&isNaN(a)&&isNaN(b))}while(++k<l)if(k in o&&sameOrNaN(o[k],value))return k;return -1});

// adds classList support (as Array) to Element.prototype for IE8-9
Object.defineProperty(Element.prototype,'classList',{
    get:function(){
        var element=this,domTokenList=(element.getAttribute('class')||'').replace(/^\s+|\s$/g,'').split(/\s+/g);
        if (domTokenList[0]==='') domTokenList.splice(0,1);
        function setClass(){
            if (domTokenList.length > 0) element.setAttribute('class', domTokenList.join(' ');
            else element.removeAttribute('class');
        }
        domTokenList.toggle=function(className,force){
            if (force!==undefined){
                if (force) domTokenList.add(className);
                else domTokenList.remove(className);
            }
            else {
                if (domTokenList.indexOf(className)!==-1) domTokenList.splice(domTokenList.indexOf(className),1);
                else domTokenList.push(className);
            }
            setClass();
        };
        domTokenList.add=function(){
            var args=[].slice.call(arguments)
            for (var i=0,l=args.length;i<l;i++){
                if (domTokenList.indexOf(args[i])===-1) domTokenList.push(args[i])
            };
            setClass();
        };
        domTokenList.remove=function(){
            var args=[].slice.call(arguments)
            for (var i=0,l=args.length;i<l;i++){
                if (domTokenList.indexOf(args[i])!==-1) domTokenList.splice(domTokenList.indexOf(args[i]),1);
            };
            setClass();
        };
        domTokenList.item=function(i){
            return domTokenList[i];
        };
        domTokenList.contains=function(className){
            return domTokenList.indexOf(className)!==-1;
        };
        domTokenList.replace=function(oldClass,newClass){
            if (domTokenList.indexOf(oldClass)!==-1) domTokenList.splice(domTokenList.indexOf(oldClass),1,newClass);
            setClass();
        };
        domTokenList.value = (element.getAttribute('class')||'');
        return domTokenList;
    }
});
@superdweebie,感谢您的关注。我已经修复了我的答案
2021-04-04 14:58:22
第一个代码很好地剪断了它,但缺少两个右括号)
2021-04-12 14:58:22
    /**
 * Method that checks whether cls is present in element object.
 * @param  {Object} ele DOM element which needs to be checked
 * @param  {Object} cls Classname is tested
 * @return {Boolean} True if cls is present, false otherwise.
 */
function hasClass(ele, cls) {
    return ele.getAttribute('class').indexOf(cls) > -1;
}

/**
 * Method that adds a class to given element.
 * @param  {Object} ele DOM element where class needs to be added
 * @param  {Object} cls Classname which is to be added
 * @return {null} nothing is returned.
 */
function addClass(ele, cls) {
    if (ele.classList) {
        ele.classList.add(cls);
    } else if (!hasClass(ele, cls)) {
        ele.setAttribute('class', ele.getAttribute('class') + ' ' + cls);
    }
}

/**
 * Method that does a check to ensure that class is removed from element.
 * @param  {Object} ele DOM element where class needs to be removed
 * @param  {Object} cls Classname which is to be removed
 * @return {null} Null nothing is returned.
 */
function removeClass(ele, cls) {
    if (ele.classList) {
        ele.classList.remove(cls);
    } else if (hasClass(ele, cls)) {
        ele.setAttribute('class', ele.getAttribute('class').replace(cls, ' '));
    }
}
+1,但是:ele.getAttribute('class')在某些情况下返回了 null(也许还没有设置 class 属性?) - 一个简单的 if 语句解决了它。
2021-03-29 14:58:22

看一下这个

Object.defineProperty(Element.prototype, 'classList', {
    get: function() {
        var self = this, bValue = self.className.split(" ")

        bValue.add = function (){
            var b;
            for(i in arguments){
                b = true;
                for (var j = 0; j<bValue.length;j++)
                    if (bValue[j] == arguments[i]){
                        b = false
                        break
                    }
                if(b)
                    self.className += (self.className?" ":"")+arguments[i]
            }
        }
        bValue.remove = function(){
            self.className = ""
            for(i in arguments)
                for (var j = 0; j<bValue.length;j++)
                    if(bValue[j] != arguments[i])
                        self.className += (self.className?" " :"")+bValue[j]
        }
        bValue.toggle = function(x){
            var b;
            if(x){
                self.className = ""
                b = false;
                for (var j = 0; j<bValue.length;j++)
                    if(bValue[j] != x){
                        self.className += (self.className?" " :"")+bValue[j]
                        b = false
                    } else b = true
                if(!b)
                    self.className += (self.className?" ":"")+x
            } else throw new TypeError("Failed to execute 'toggle': 1 argument required")
            return !b;
        }

        return bValue; 
    },
    enumerable: false
})

和 classList 将工作!

document.getElementsByTagName("div")[0].classList
["aclass"]

document.getElementsByTagName("div")[0].classList.add("myclass")

document.getElementsByTagName("div")[0].className
"aclass myclass"

就这样!

我将此代码插入到违规代码正上方的脚本块中 - 效果很好。谢谢。
2021-03-24 14:58:22
我是菜鸟。我把上面的放在哪里?在 <script> 中还是在 <style> 中?
2021-03-27 14:58:22
干得好,不幸的是这在所有情况下都不适合我,但是我确实找到了这个:github.com/remy/polyfills/blob/...
2021-03-27 14:58:22