js获取类名的3种方法(教你js对象删除某个元素)

本内容是《Web前端开发之Javascript视频》的课件,请配合大师哥《Javascript》视频课程学习。

JavaScript也可以针对CSS进行编程,也就是所谓的脚本化CSS;通过脚本化CSS,同样可以达到一系列的视觉效果;

在HTML中定义样式的方式有3种:通过元素包含外部样式表文件、使用

mydiv

注:以上border属性可能不会返回实际的border规则(如IE和Firefox返回空字符串),原因是不同浏览中解释复合属性的方式不同,因为设置这种属性实际上会涉及很多其他属性,例如:border,实际上调协了四个边的边框宽度、颜色等,因此border不会返回,但
computedStyle.borderleftWidth会返回值;

console.log(computedStyle.borderLeftWidth);
console.log(computedStyle.borderLeftColor);

另外,不同浏览器表示值的方式可能会有所区别;

计算后的样式也包含属于浏览器内部样式表的样式信息,因此任何具有默认值的CSS属性都会表现在计算后的样式中;如visibility属性都有一个默认值,有些浏览器设置为visible,而有些设置为inherit;

计算样式的CSSStyleDeclaration对象和表示内联样式的对象之间有一些重要的区别:

计算样式的属性是只读的;

计算样式的值是绝对值,类似百分比和点之类的相对的单位将全部转换为绝对值;所有指定尺寸,例如外边距大小和字体大小等属性都有一个以像素为度量单位的值;相关颜色的属性将以”rgb(#,#,#)”或”rgba(#,#,#,#)”的格式返回;

不计算复合属性,它们只基于最基础的属性,例如,不要查询margin属性,应该使用marginLeft或marginTop等;

计算样式的cssText属性未定义(也就是该属性返回空字符串);

计算样式和内联样式可以同时使用;

// 用指定的因子缩放元素e的文本尺寸
function scale(e, factor){
// 用计算样式查询当前文本的尺寸
var size = parseInt(window.getComputedStyle(e,"").fontSize);
// 用内联样式来放大尺寸
e.style.fontSize = factor * size + "px";
}
// 用指定的因子修改元素的背景颜色
// factors > 1 颜色变浅,factors < 1颜色变暗
function scaleColor(e, factor){
var color = window.getComputedStyle(e,"").backgroundColor;
var components = color.match(/[d.]+/g); // 解析r、g、b分量
for(var i=0; i<3; i++){ // 循环r,g,b
var x = Number(components[i]) * factor; // 缩放每个值
x = Math.round(Math.min(Math.max(x, 0), 255)); // 设置边界并取整
components[i] = String(x);
}
if(components.length == 3) // rgb()颜色
e.style.backgroundColor = "rgb(" + components.join() + ")";
else // rgba()颜色
e.style.backgroundColor = "rgba(" + components.join() + ")";
}
var mydiv = document.getElementById("mydiv");
scale(mydiv, 1.5);
scaleColor(mydiv, .5);

低版本的IE不支持getComputedStyle()方法,但它有一种类似的概念;在IE中,具有style属性的元素还有一个currentStyle属性,该属性是CSSStyleDeclaration的实例,包含当前元素全部计算后的样式,但只有IE支持;

var computedStyle = mydiv.currentStyle;
console.log(computedStyle.backgroundColor);
console.log(computedStyle.width);
console.log(computedStyle.height);
console.log(computedStyle.borderLeftWidth);

兼容函数:

function getStyle(obj, attr){
if(window.getComputedStyle)
return getComputedStyle(obj, null)[attr];
else
return obj.currentStyle[attr];
}
var mydiv = document.getElementById("mydiv");
var backgroundColor = getStyle(mydiv, "background-color");
console.log(backgroundColor); // rgb(245, 222, 179)
// 或者
function getCss(obj, css){
return (document.defaultView.getComputedStyle ?
document.defaultView.getComputedStyle(obj,null) :
obj.currentStyle)[css];
}
var borderTopWidth = getCss(mydiv, "border-top-width");
console.log(borderTopWidth); // 1px

封装一下函数,用来获取CSS属性值,如:

function getComputedStyles(elem,prop) {
var cs = window.getComputedStyle(elem,null);
if (prop) {
console.log(prop+" : "+cs.getPropertyValue(prop));
return;
}
var len = cs.length;
for (var i=0;i var style = cs[i];
console.log(style+" : "+cs.getPropertyValue(style));
}
}
getComputedStyles(mydiv); // 查询所有
getComputedStyles(mydiv,"background-color"); // 只查询一个属性

与伪元素一起使用:getComputedStyle可以从伪元素中提取样式信息(例如:::after, ::before, ::marker, ::line-marker);



使用计算样式是可以获取元素的几何尺寸和位置的,但是其获得的结果并不一定是我们所期望的,此时可以使用getBoundingClientRect(),其返回的值是与呈现的效果是一致的;

console.log(computedStyle.left); // auto
console.log(computedStyle.top); // auto
console.log(computedStyle.width); // 300px
// left:8 top:8 width:302,包括了border
var rect = mydiv.getBoundingClientRect();
console.log(rect);

脚本化CSS类:

也可以脚本化元素的class属性,改变元素的class就改变了应用于元素的一组样式表选择器,它能在同一时刻改变多个CSS属性;

className属性:

与元素的class特性对应,即为元素指定的CSS类;由于class是ECMAScript保留字,所以在Javascript中使用className;

在操作类名时,需要通过className属性添加、删除和替换类名;

var mydiv = document.getElementById("mydiv");
mydiv.className = "container"; // 设置
mydiv.className = ""; // 删除
mydiv.className = "other"; // 替换
// 或
if(mydiv.className == ""){
mydiv.className = "container";
}

元素可以设置多个CSS类,其className中保存的是拥有多个类名的字符串,因此即使只修改字符串一部分,都会覆盖之前的值,所以每次都必须设置整个字符串的值;

var mydiv = document.getElementById("mydiv");
console.log(mydiv.className); // db user disable
mydiv.className = "container";
console.log(mydiv.className); // container

如果要从class中只删除一个类名,需要把多个类名拆开,删除不想要的那个,然后再把其他类名拼成一个新字符串,如:

// 如,删除user类
// 首先,取得类名字符串并拆分成数组
var mydiv = document.getElementById("mydiv");
var classNames = mydiv.className.split(/s+/);
// 找到要删的类名
var pos = -1, i, len;
for(i=0, len = classNames.length; i if(classNames[i] == "user"){
pos = i;
break;
}
}
// 删除类名
classNames.splice(i,1);
// 把剩下的类名拼成字符串并重新设置
mydiv.className = classNames.join(" ");

如果要添加类名,是可以直接通过拼接字符串完成,但在拼接之前,必须要通过检测确定不会多次添加相同的类名;

Element.classList属性:

HTML5新增了一种操作类名的方式,可以让操作更简单也更安全,即classList属性,其是一个DOMTokenList对象,其是只读的类数组对象,与其他DOM集合类似,它也有一个表示自己包含多少个元素的length属性,而要取得每个元素可以使用item()方法,也可以使用方括号语法,此外,这个新类型还定义如下的方法:

  • add(value):将给定的字符串值添加到列表中,如果值存在,就不添加;
  • contains(value):表示列表中是否存在给定的值,如果存在返回true,否则,返回false;
  • remove(value):从列表中删除给定的字符串;
  • toggle(value):如果列表中已经存在给定的值,删除它,否则,添加它;

console.log(mydiv.classList); // DOMTokenList
mydiv.classList.add("container");
mydiv.classList.remove("container");

使用classList,可以确保其他类名不受此次修改的影响,可以极大地减少类似的基本操作的复杂性;

mydiv.classList.toggle("user"); // 切换user类
// 确定元素中是否包含既定的类名
if(mydiv.classList.contains("bd") && !mydiv.classList.contains("disabled")){
// To Do
}
// 迭代类名
for(var i=0,len=mydiv.classList.length; i // To Do
console.log(mydiv.classList[i]);
}

有了classList属性,除非需要全部删除所有类名,或者完全重写元素的class属性,否则也就用不到className了;

需要确定的一点,classList这个DOMTokenList对象,它是实时的,如果className属性改变了,它也会及时更新,同样的,classList改变了,className属性也会及时更新;

IE9以下的浏览器不支持classList属性,可以自定义一个CSSClassList类,模拟DOMTokenList对象的方法;

function classList(e){
// 以下两行先注释,否则后面的toArray默认调用的是DOMTokenList对象的的toArray,而它并不存在
// 或者扩展内置的DOMTokenList的toArray
// if(e.classList) return e.classList; // 如果e.classList存在,则返回它
// else return new CSSClassList(e); // 否则,说伪造一个
return new CSSClassList(e);
}
// CSSClassList是一个模拟DOMTokenList的对象
function CSSClassList(e) { this.e = e;}
// 如果e.className包含类名c则返回true,否则返回false
CSSClassList.prototype.contains = function(c){
// 检查c是否是合法的类名
if(c.length === 0 || c.indexOf(" ") != -1)
throw new Error("Invalid class name: '" + c + "'");
// 首先是常规检查
var classes = this.e.className;
if(!classes) return false; // e不含类名
if(classes === c) return true; // e有一个完全匹配的类名
// 否则,把c自身看做一个单词,利用正则表达式搜索c
return classes.search("b" + c + "b") != -1;
};
// 如果c不存在,将c添加到e.className中
CSSClassList.prototype.add = function(c){
if(this.contains(c)) return; // 如果存在,什么也不做
var classes = this.e.className;
if(classes && classes[classes.length - 1] != " ")
c = " " + c; // 如果需要加一个空格
this.e.className += c; // 将c添加到className中
};
// 将在e.className中出现的所有c都删除
CSSClassList.prototype.remove = function(c){
if(c.length === 0 || c.indexOf(" ") != -1)
throw new Error("Invalid class name: '" + c + "'");
// 将所有作为单词的c和多余的尾随空格全部删除
var pattern = new RegExp("b" + c + "bs*", "g");
this.e.className = this.e.className.replace(pattern, "");
};
// 如果c不存在,将c添加到e.className中,并返回true
// 否则,将e.className中出现的所有c都删除,并返回false
CSSClassList.prototype.toggle = function(c){
if(this.contains(c)){ // 如果e.className包含类名c
thsi.remove(); // 删除它
return false;
}else{
this.add(c); // 添加
return true;
}
};
// 返回e.className本身
CSSClassList.prototype.toString = function(){
return this.e.className;
};
// 返回在e.className中的类名
CSSClassList.prototype.toArray = function(){
return this.e.className.match(/bw+b/g) || [];
};
// 应用
var mydiv = document.getElementById("mydiv");
var ccl = classList(mydiv);
console.log(ccl);
console.log(ccl.contains("newsdiv")); // true
ccl.add("topDiv");
ccl.remove("newsdiv");
ccl.toggle("newsdiv");
console.log(ccl.toString());
console.log(ccl.toArray());

脚本化样式表:

在脚本化样式表时,会使用到两种类型的对象:

第一类是元素对象,包括通过元素包含的样式表和在

加载中~
每日一言
不怕万人阻挡,只怕自己投降
Not afraid of people blocking, I'm afraid their surrender