DOM与样式
elem.className 与 elem.classList
className
对于修改元素的样式,首选修改类名的方式修改样式。
elem.className 对应于标签的 class attribute,如果我们修改一个 DOM 节点对象的 className 属性,那么会对标签的 class attribute 内容进行直接替换。
classList
elem.classList 是一个类数组,可以获取到一个元素的多个类名。
const div = document.createElement("div");
div.className = "class1 class2 class3";
div.classList; // ["class1", "class2", "class3"]
此时 div.classList 的结构如下:
0: "class1"
1: "class2"
2: "class3"
length: 3
value: "class1 class2 class3"
该类数组上还有如下方法。
| 方法 | 说明 | 
|---|---|
elem.classList.add(class) | 给当前元素添加指定类名 | 
elem.classList.remove(class) | 给当前元素移除指定类名 | 
elem.classList.toggle(class) | 如果类名存在则移除,类名不存在则添加 | 
elem.classList.contains(class) | 判断是否还有某个类名 | 
elem.classList.replace(oldClass, newClass) | 将旧类名替换为新类名 | 
elem.classList.forEach(callback, thisArg) | 遍历 classList | 
修改 DOM 元素样式
elem.style
elem.style 是一个只读对象,我们修改 elem.style 上的属性,等价于给对应标签通过 style attribute 添加内联样式。
比如,elem.style.width = "100px" 等价于 <div id="elem" style="width: 100px;"></div>。
在 elem.style 对象上的样式属性都是以驼峰命名方式存在的。
background-color  => elem.style.backgroundColor
z-index           => elem.style.zIndex
border-left-width => elem.style.borderLeftWidth
如果你想删除(重制)一个内联样式,你可以将 elem.style 上相应的属性赋值为空字符串。
注意事项
- 使用 
elem.style.xxx添加某个内联样式时注意不要忘记将 CSS 单位添加到值上 - 对于一些简写属性,比如 
elem.style.margin,我们对其赋值后,浏览器会推断出elem.style.marginLeft/Right/Top/Bottom的值 
elem.style.cssText
我们不能像这样 elem.style = "color: red; width: 100px" 设置完整的属性,因为 div.style 是一个对象,并且它是只读的。
但是我们可以使用 elem.style.cssText 来读写标签上的 style attribute。
elem.style.cssText = `
  color: red !important;
  background-color: yellow;
  width: 100px;
  text-align: center;
`;
我们很少使用这个属性,因为这样的赋值会重制整个内联样式。
我们也可以使用 elem.setAttribute("style") 来实现相同效果。
elem.setAttribute("style", `
  color: red !important;
  background-color: yellow;
  width: 100px;
  text-align: center;
`);
读取 DOM 元素样式计算值
window.getComputedStyle
window.getComputedStyle(element[, pseudo])
elem.style 的作用仅仅是对一个元素的内联样式进行读写。如果我们想要获取到一个元素所有层叠样式的 计算值 则可以使用 window.getComputedStyle 方法。
<body>
  <style>
    div {
      color: green;
      font-size: 1.15rem;
    }
  </style>
  <div style="color: red">Hello World</div>
  <div>Hello World</div>
</body>
<script>
  const elems = document.querySelectorAll("div");
  window.getComputedStyle(elems[0]).color; // 'rgb(255, 0, 0)' 红色
  window.getComputedStyle(elems[1]).color; // 'rgb(0, 128, 0)' 绿色
  window.getComputedStyle(elems[1]).fontSize; // '18.4px'
</script>
什么是样式的计算值?
比如我们给根元素设置了 font-size: 2rem,这样的相对单位的取值,最终会被浏览器解析为 px 单位的数值,这个就是计算值,在 Chrome 开发者工具中选中某个元素后,切换到 Computed 就可以查看这个元素所有样式的计算值了。
该方法还有第二个可选参数,用于指定某个元素的 伪元素 或者 伪类,这样我们就可以获取某个元素的 伪元素 或者 伪类 的计算样式了。
<body>
  <style>
    div::after {
      content: "123";
      color: green;
      font-size: 1.15rem;
    }
    
    div:hover {
      color: red;
    }
  </style>
  <div>Hello World</div>
</body>
<script>
  const elem = document.querySelector("div");
  window.getComputedStyle(elem, "::after").content; // '123'
  window.getComputedStyle(elem, ":hover").color; // 'rgb(0, 0, 0)' 黑色
</script>
关于元素的伪类
上面的例子中,div:hover 的 color 计算值依旧是黑色,原因是执行该行代码时,我们的鼠标并没有悬浮在 div 元素之上,如果我们悬浮在 div 元素之上,再执行该行元素,那么 color 计算值就会变成红色。
由于隐私问题,链接的 :visited 伪类样式被隐藏了。
不要直接读取 width 和 height 属性
如果你想获取一个元素的尺寸,请可以使用 clientWidth 或 offsetWidth(后面会讲到)。
如果你直接使用 window.getComputedStyle(elem).width,那么对于一个内联元素来说取值可能就是 auto,并且如果元素具有滚动条,那么 width 实际上还会减去滚动条的宽度,因为本质上我们使用该方法读取的是 content 的 width 和 height,而且这个还和 box-sizing 的取值有关。