知乎文章地址:https://zhuanlan.zhihu.com/p/52423430
之前面试的时候考到对html元素的class进行增删改,然后有前辈说如果使用classList并且通过原型实现兼容,会非常满意,由此想到对getElementsByClassName与classList这两个接口进行浏览器兼容。不过目前仅兼容到ie8,下面是具体的一些方案:
兼容getElementsByClassName:
// 兼容getElementsByClassName
if (!(\'getElementsByClassName\' in document)) {
function getElementsByClassName (classList) {
if (typeof classList !== \'string\') throw TypeError(\'the type of classList is error\')
// 获取父元素
var parent = this
// 获取相应子元素
var child = parent.getElementsByTagName(\'*\')
var nodeList = []
// 获得classList的每个类名 解决前后空格 以及两个类名之间空格不止一个问题
var classAttr = classList.replace(/^\\s+|\\s+$/g, \'\').split(/\\s+/)
for (var j = 0, len = child.length; j < len; j++) {
var element = child[j]
for (var i = 0, claLen = classAttr.length; i < claLen; i++) {
var className = classAttr[i]
if (element.className.search(new RegExp(\'(\\\\s+)?\'+className+\'(\\\\s+)?\')) === -1) break
}
if (i === claLen) nodeList.push(element)
}
return nodeList
}
// 兼容ie5及以上的document的getElementsByClassName接口
document.getElementsByClassName = getElementsByClassName
// 兼容ie8及以上的getElementsByClassName接口
window.Element.prototype.getElementsByClassName = getElementsByClassName
}
兼容classList:
// 兼容classList
// 定义一个classList对象
function ClassList (obj) {
this.obj = obj
}
// 提取add、remove和contains中的公共方法
function op (self, valArr, tag) {
var className = self.obj.className
if (tag === 2) {
if (valArr.length === 0) throw TypeError(\"Failed to execute \'contains\' on \'DOMTokenList\': 1 argument required, but only 0 present.\")
if (typeof valArr[0] !== \'string\' || !!~valArr[0].search(/\\s+/g)) return false
return !!~className.search(new RegExp(valArr[0]))
}
for (var i in valArr) {
if(typeof valArr[i] !== \'string\' || !!~valArr[i].search(/\\s+/g)) throw TypeError(\'the type of value is error\')
var temp = valArr[i]
var flag = !!~className.search(new RegExp(\'(\\\\s+)?\'+temp+\'(\\\\s+)?\'))
if (tag === 1) {
!flag ? className += \' \' + temp : \'\'
} else if (tag === 3) {
flag ? className = className.replace(new RegExp(\'(\\\\s+)?\'+temp),\'\') : \'\'
}
}
self.obj.className = className
}
ClassList.prototype.add = function () {
var self = this
op(self, arguments, 1)
}
ClassList.prototype.contains = function () {
var self = this
return op(self, arguments, 2)
}
ClassList.prototype.item = function (index) {
typeof index === \'string\' ? index = parseInt(index) : \'\'
if (arguments.length === 0 || typeof index !== \'number\') throw TypeError(\"Failed to execute \'toggle\' on \'DOMTokenList\': 1 argument required, but only 0 present.\")
var claArr = this.obj.className.replace(/^\\s+|\\s+$/, \'\').split(/\\s+/)
var len = claArr.length
if (index < 0 || index >= len) return null
return claArr[index]
}
ClassList.prototype.remove = function () {
var self = this
op(self, arguments, 3)
}
ClassList.prototype.toggle = function (value) {
if(typeof value !== \'string\' || arguments.length === 0) throw TypeError(\"Failed to execute \'toggle\' on \'DOMTokenList\': 1 argument(string) required, but only 0 present.\")
if (arguments.length === 1) {
this.contains(value) ? this.remove(value) : this.add(value)
return
}
!arguments[1] ? this.remove(value) : this.add(value)
}
var div = document.createElement(\"div\")
if (undefined === div.classList) {
console.log(111)
// 兼容ie8及以上的classList,不过对于ie8需要加上括号
window.Element.prototype.classList = function () {
return new ClassList(this)
}
}
// 封装一个方法获取classList(因为上面封装的是一个函数,为了统一调用,采用下面的方法)
function getClassList (el) {
if (!el) throw TypeError(\"Failed to execute \'getClassList\': 1 argumen required, but only 0 present.\")
if (typeof el.classList === \'function\') {
return el.classList()
}
return el.classList
}
上面这种方法稍微有点繁琐,正常来说我们想要实现仅仅访问classList属性即可,故而,我们可以采用以下的方法,同样兼容到ie8:
if (!(\"classList\" in document.documentElement)) {
.defineProperty(window.Element.prototype, \'classList\', {
get: function () {
var self = this
function update(fn) {
return function () {
var className = self.className.replace(/^\\s+|\\s+$/g, \'\'),
valArr = arguments
return fn(className, valArr)
}
}
function add_rmv (className, valArr, tag) {
for (var i in valArr) {
if(typeof valArr[i] !== \'string\' || !!~valArr[i].search(/\\s+/g)) throw TypeError(\'the type of value is error\')
var temp = valArr[i]
var flag = !!~className.search(new RegExp(\'(\\\\s+)?\'+temp+\'(\\\\s+)?\'))
if (tag === 1) {
!flag ? className += \' \' + temp : \'\'
} else if (tag === 2) {
flag ? className = className.replace(new RegExp(\'(\\\\s+)?\'+temp),\'\') : \'\'
}
}
self.className = className
return tag
}
return {
add: update(function (className, valArr) {
add_rmv(className, valArr, 1)
}),
remove: update(function (className, valArr) {
add_rmv(className, valArr, 2)
}),
toggle: function (value) {
if(typeof value !== \'string\' || arguments.length === 0) throw TypeError(\"Failed to execute \'toggle\' on \'DOMTokenList\': 1 argument(string) required, but only 0 present.\")
if (arguments.length === 1) {
this.contains(value) ? this.remove(value) : this.add(value)
return
}
!arguments[1] ? this.remove(value) : this.add(value)
},
contains: update(function (className, valArr) {
if (valArr.length === 0) throw TypeError(\"Failed to execute \'contains\' on \'DOMTokenList\': 1 argument required, but only 0 present.\")
if (typeof valArr[0] !== \'string\' || !!~valArr[0].search(/\\s+/g)) return false
return !!~className.search(new RegExp(valArr[0]))
}),
item: function (index) {
typeof index === \'string\' ? index = parseInt(index) : \'\'
if (arguments.length === 0 || typeof index !== \'number\') throw TypeError(\"Failed to execute \'toggle\' on \'DOMTokenList\': 1 argument required, but only 0 present.\")
var claArr = self.className.replace(/^\\s+|\\s+$/, \'\').split(/\\s+/)
var len = claArr.length
if (index < 0 || index >= len) return null
return claArr[index]
}
}
}
})
}
值得注意的是,ie10、11虽然支持classList,但是其中add和remove方法不支持删除多个class,另外对于toggle方法,其传入的第二个布尔类型的参数无效。
另外提示,数组的indexOf方法不支持ie8及以下的浏览器。
最后,分享一下鄙人的github地址~~~浏览器兼容研究学习:
继续阅读与本文标签相同的文章
上一篇 :
Fastai深度学习课程的八大最佳实践
下一篇 :
BITACM2018第二轮积分赛(一)题解
-
两问快递涨价
2026-05-19栏目: 教程
-
一图了解顺丰全球供应链网络布局
2026-05-19栏目: 教程
-
这款 IDE 插件再次升级,让「小程序云」的开发部署提速 8 倍
2026-05-19栏目: 教程
-
专注于技术能力提升的央企,注定不平凡,我有看点!
2026-05-19栏目: 教程
-
男友力爆棚的Mac电脑办公软件WPS Office
2026-05-19栏目: 教程
