pin_drop当前位置:知识文库 ❯ 图文
JS集成:HTML DOM修改样式 - 详细教程与实战指南
教程简介
DOM样式操作是前端开发中实现动态交互效果的核心手段。通过JavaScript修改元素的样式,可以实现动画效果、主题切换、响应式布局调整、用户界面反馈等功能。浏览器提供了多种样式操作方式,包括style属性、cssText、getComputedStyle、classList和CSS变量操作等。本教程将全面讲解这些样式操作方法的使用、区别、性能考虑以及样式优先级规则。
核心概念
样式来源与优先级
CSS样式有多个来源,它们的优先级从低到高为:
浏览器默认样式:浏览器内置的默认样式
外部样式表:通过
<link>引入的CSS文件内部样式表:
<style>标签中的样式内联样式:元素的
style属性!important声明:最高优先级(应尽量避免使用)
行内样式vs计算样式
行内样式(Inline Style):通过
element.style访问,只包含style属性中设置的样式计算样式(Computed Style):通过
getComputedStyle()获取,包含所有来源的最终计算结果
语法与用法
1. style属性
style 属性用于读取和设置元素的内联样式。
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>style属性示例</title>
<style>
.box { width: 200px; height: 200px; background: #f0f0f0; }
</style>
</head>
<body>
<div id="demo" class="box" style="color: red;">示例元素</div>
<script>
var demo = document.getElementById('demo');
// 读取内联样式(只能读取style属性中设置的样式)
console.log(demo.style.color); // "red"
console.log(demo.style.width); // ""(空字符串,因为width在CSS类中设置,不在style属性中)
// 设置内联样式
demo.style.color = 'blue';
demo.style.backgroundColor = '#ffcc00';
demo.style.fontSize = '20px';
demo.style.marginTop = '10px';
demo.style.borderRadius = '8px';
// CSS属性名到JavaScript属性名的转换规则:
// CSS: background-color -> JS: backgroundColor
// CSS: font-size -> JS: fontSize
// CSS: border-radius -> JS: borderRadius
// CSS: margin-top -> JS: marginTop
// 规则:去掉连字符,连字符后的首字母大写(驼峰命名)
// 特殊属性名:
// CSS: float -> JS: cssFloat(因为float是JS保留字)
demo.style.cssFloat = 'left';
// 读取时注意:style属性只能读取内联样式
// CSS类中设置的样式无法通过style属性读取
console.log(demo.style.background); // ""(空,因为在CSS类中设置)
</script>
</body>
</html>2. cssText
cssText 属性用于一次性设置或读取元素的整个内联样式字符串。
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>cssText示例</title>
</head>
<body>
<div id="demo">示例元素</div>
<script>
var demo = document.getElementById('demo');
// 设置cssText(会覆盖所有已有的内联样式)
demo.style.cssText = 'color: white; background: #333; padding: 20px; border-radius: 8px;';
// 读取cssText
console.log(demo.style.cssText);
// "color: white; background: #333; padding: 20px; border-radius: 8px;"
// 追加样式(注意:直接赋值会覆盖)
demo.style.cssText += ' font-size: 18px;';
// 清除所有内联样式
demo.style.cssText = '';
// cssText vs 逐个设置style属性
// cssText优点:一次性设置多个样式,只触发一次重排
// cssText缺点:会覆盖已有内联样式
// 逐个设置
demo.style.color = 'white';
demo.style.background = '#333';
demo.style.padding = '20px';
// 每次设置都可能触发重排(浏览器会优化批量设置)
</script>
</body>
</html>3. getComputedStyle
getComputedStyle 方法获取元素的所有最终计算样式,包括来自CSS类、继承和内联样式的所有样式。
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>getComputedStyle示例</title>
<style>
.container {
width: 300px;
padding: 20px;
background: #f5f5f5;
font-size: 16px;
line-height: 1.5;
color: #333;
}
</style>
</head>
<body>
<div id="demo" class="container" style="color: red;">示例元素</div>
<script>
var demo = document.getElementById('demo');
// 获取计算样式
var computedStyle = window.getComputedStyle(demo);
// 读取各种样式属性
console.log(computedStyle.color); // "rgb(255, 0, 0)"(内联样式优先)
console.log(computedStyle.width); // "300px"
console.log(computedStyle.padding); // "20px"
console.log(computedStyle.fontSize); // "16px"
console.log(computedStyle.lineHeight); // "24px" 或 "1.5"(取决于浏览器)
console.log(computedStyle.backgroundColor); // "rgb(245, 245, 245)"
console.log(computedStyle.display); // "block"
console.log(computedStyle.position); // "static"
// 获取特定属性值
var width = window.getComputedStyle(demo).width;
console.log('宽度:', width);
// 获取伪元素样式
var beforeStyle = window.getComputedStyle(demo, '::before');
console.log('::before content:', beforeStyle.content);
// 注意事项:
// 1. 返回值是只读的,不能修改
// 2. 返回的是计算后的绝对值(如颜色转为rgb,相对单位转为px)
// 3. 某些属性返回值可能因浏览器而异
// 4. 读取计算样式会触发重排
// 获取数值(去掉单位)
var widthValue = parseFloat(computedStyle.width);
console.log('宽度数值:', widthValue); // 300
</script>
</body>
</html>4. classList
classList 属性返回元素的类名列表,提供了方便的方法来操作类名。
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>classList示例</title>
<style>
.box { padding: 20px; border: 1px solid #ddd; border-radius: 8px; margin: 8px 0; }
.active { background: #007bff; color: white; }
.highlight { background: #fff3cd; border-color: #ffc107; }
.hidden { display: none; }
.large { font-size: 24px; }
.bold { font-weight: bold; }
</style>
</head>
<body>
<div id="demo" class="box">示例元素</div>
<script>
var demo = document.getElementById('demo');
// add:添加类名
demo.classList.add('active');
demo.classList.add('highlight', 'bold'); // 添加多个类名
// remove:移除类名
demo.classList.remove('highlight');
demo.classList.remove('bold', 'large'); // 移除多个类名
// toggle:切换类名(存在则移除,不存在则添加)
demo.classList.toggle('active'); // 移除active
demo.classList.toggle('active'); // 添加active
// toggle带强制参数
demo.classList.toggle('active', true); // 强制添加(等同于add)
demo.classList.toggle('active', false); // 强制移除(等同于remove)
// contains:检测是否包含类名
console.log(demo.classList.contains('box')); // true
console.log(demo.classList.contains('active')); // 取决于当前状态
// replace:替换类名
demo.classList.replace('active', 'highlight');
// 遍历类名
demo.classList.forEach(function(className) {
console.log('类名:', className);
});
// 类名数量
console.log('类名数量:', demo.classList.length); // 2
// 通过索引访问
console.log('第一个类名:', demo.classList.item(0)); // "box"
// 旧方式:使用className(字符串操作,不推荐)
// 添加类名
demo.className += ' new-class';
// 移除类名(麻烦且容易出错)
demo.className = demo.className.replace(/\bnew-class\b/, '').trim();
</script>
</body>
</html>5. className
className 属性获取或设置元素的class属性值(字符串形式)。
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>className示例</title>
</head>
<body>
<div id="demo" class="box primary large">示例元素</div>
<script>
var demo = document.getElementById('demo');
// 读取className
console.log(demo.className); // "box primary large"
// 设置className(替换所有类名)
demo.className = 'new-class';
console.log(demo.className); // "new-class"
// 追加类名
demo.className += ' another-class';
console.log(demo.className); // "new-class another-class"
// className vs classList
// className:字符串操作,适合需要整体替换类名的场景
// classList:API操作,适合增删单个类名的场景
// 推荐使用classList进行单个类名操作
demo.classList.add('safe-add');
demo.classList.remove('safe-add');
demo.classList.toggle('safe-toggle');
</script>
</body>
</html>6. CSS变量操作
CSS自定义属性(CSS变量)可以通过JavaScript动态修改。
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>CSS变量操作示例</title>
<style>
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
--font-size-base: 16px;
--border-radius: 8px;
--spacing: 16px;
}
.card {
padding: var(--spacing);
border: 1px solid #ddd;
border-radius: var(--border-radius);
margin: var(--spacing) 0;
font-size: var(--font-size-base);
}
.card h3 {
color: var(--primary-color);
margin-top: 0;
}
.card .btn {
background: var(--primary-color);
color: white;
border: none;
padding: 8px 16px;
border-radius: var(--border-radius);
cursor: pointer;
}
</style>
</head>
<body>
<div class="card" id="theme-card">
<h3>CSS变量操作演示</h3>
<p>通过修改CSS变量实现主题切换</p>
<button class="btn" onclick="switchTheme('blue')">蓝色主题</button>
<button class="btn" onclick="switchTheme('green')">绿色主题</button>
<button class="btn" onclick="switchTheme('purple')">紫色主题</button>
</div>
<script>
// 读取CSS变量
var root = document.documentElement;
var computedStyle = getComputedStyle(root);
console.log('主色:', computedStyle.getPropertyValue('--primary-color')); // " #007bff"
// 设置CSS变量(在根元素上)
function switchTheme(theme) {
var themes = {
blue: {
'--primary-color': '#007bff',
'--secondary-color': '#6c757d'
},
green: {
'--primary-color': '#28a745',
'--secondary-color': '#20c997'
},
purple: {
'--primary-color': '#6f42c1',
'--secondary-color': '#e83e8c'
}
};
var selectedTheme = themes[theme];
Object.keys(selectedTheme).forEach(function(varName) {
root.style.setProperty(varName, selectedTheme[varName]);
});
}
// 在特定元素上设置CSS变量
var card = document.getElementById('theme-card');
card.style.setProperty('--spacing', '24px'); // 只影响此元素及其后代
// 读取元素上的CSS变量
var cardStyle = getComputedStyle(card);
console.log('卡片间距:', cardStyle.getPropertyValue('--spacing'));
// 移除CSS变量
card.style.removeProperty('--spacing');
</script>
</body>
</html>代码示例
示例1:主题切换系统
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>主题切换系统</title>
<style>
:root {
--bg-primary: #ffffff;
--bg-secondary: #f5f5f5;
--text-primary: #333333;
--text-secondary: #666666;
--border-color: #dddddd;
--accent-color: #007bff;
--accent-hover: #0056b3;
--shadow: 0 2px 8px rgba(0,0,0,0.1);
--transition-speed: 0.3s;
}
[data-theme="dark"] {
--bg-primary: #1a1a2e;
--bg-secondary: #16213e;
--text-primary: #e0e0e0;
--text-secondary: #a0a0a0;
--border-color: #333355;
--accent-color: #4fc3f7;
--accent-hover: #29b6f6;
--shadow: 0 2px 8px rgba(0,0,0,0.3);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
transition: background var(--transition-speed), color var(--transition-speed);
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
.card {
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 20px;
margin: 16px 0;
box-shadow: var(--shadow);
transition: all var(--transition-speed);
}
.card h2 { color: var(--accent-color); margin-bottom: 12px; }
.btn {
padding: 8px 16px; border: none; border-radius: 6px; cursor: pointer;
background: var(--accent-color); color: white; margin: 4px;
transition: background var(--transition-speed);
}
.btn:hover { background: var(--accent-hover); }
.theme-switch {
position: fixed; top: 20px; right: 20px;
width: 50px; height: 26px; border-radius: 13px;
background: var(--border-color); cursor: pointer;
transition: background var(--transition-speed);
}
.theme-switch::after {
content: ''; position: absolute; top: 3px; left: 3px;
width: 20px; height: 20px; border-radius: 50%;
background: white; transition: transform var(--transition-speed);
}
[data-theme="dark"] .theme-switch { background: var(--accent-color); }
[data-theme="dark"] .theme-switch::after { transform: translateX(24px); }
</style>
</head>
<body>
<div class="theme-switch" id="theme-toggle" role="button" tabindex="0" aria-label="切换主题"></div>
<h1>主题切换系统</h1>
<div class="card">
<h2>关于主题</h2>
<p>本页面使用CSS变量实现主题切换,点击右上角开关即可切换明暗主题。</p>
<p>所有颜色和阴影都通过CSS变量定义,切换主题只需更改变量值。</p>
</div>
<div class="card">
<h2>操作按钮</h2>
<button class="btn">主要按钮</button>
<button class="btn">次要按钮</button>
</div>
<script>
var themeToggle = document.getElementById('theme-toggle');
// 读取保存的主题
var savedTheme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-theme', savedTheme);
themeToggle.addEventListener('click', function() {
var currentTheme = document.documentElement.getAttribute('data-theme');
var newTheme = currentTheme === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
});
// 键盘支持
themeToggle.addEventListener('keydown', function(e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
themeToggle.click();
}
});
</script>
</body>
</html>示例2:classList实现手风琴组件
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>classList实现手风琴组件</title>
<style>
body { font-family: -apple-system, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
.accordion { border: 1px solid #ddd; border-radius: 8px; overflow: hidden; }
.accordion-item { border-bottom: 1px solid #ddd; }
.accordion-item:last-child { border-bottom: none; }
.accordion-header {
padding: 16px 20px; cursor: pointer; display: flex;
justify-content: space-between; align-items: center;
background: #f8f9fa; transition: background 0.2s;
}
.accordion-header:hover { background: #e9ecef; }
.accordion-header::after { content: '+'; font-size: 20px; font-weight: bold; transition: transform 0.3s; }
.accordion-item.open .accordion-header::after { transform: rotate(45deg); }
.accordion-body {
max-height: 0; overflow: hidden; transition: max-height 0.3s ease-out;
padding: 0 20px;
}
.accordion-item.open .accordion-body { max-height: 200px; padding: 16px 20px; }
</style>
</head>
<body>
<h1>手风琴组件</h1>
<div class="accordion" id="faq-accordion">
<div class="accordion-item" data-accordion="item">
<div class="accordion-header">什么是DOM?</div>
<div class="accordion-body">
<p>DOM(文档对象模型)是HTML文档的编程接口,它将文档表示为节点树,使JavaScript能够访问和操作页面内容。</p>
</div>
</div>
<div class="accordion-item" data-accordion="item">
<div class="accordion-header">什么是classList?</div>
<div class="accordion-body">
<p>classList是元素类名列表的API,提供了add、remove、toggle、contains和replace等方法来方便地操作类名。</p>
</div>
</div>
<div class="accordion-item" data-accordion="item">
<div class="accordion-header">什么是CSS变量?</div>
<div class="accordion-body">
<p>CSS变量(自定义属性)允许定义可复用的值,通过var()函数引用。JavaScript可以通过style.setProperty动态修改CSS变量。</p>
</div>
</div>
<div class="accordion-item" data-accordion="item">
<div class="accordion-header">如何获取元素的计算样式?</div>
<div class="accordion-body">
<p>使用window.getComputedStyle(element)方法可以获取元素的所有最终计算样式,包括CSS类、继承和内联样式的综合结果。</p>
</div>
</div>
</div>
<script>
var accordion = document.getElementById('faq-accordion');
// 事件委托
accordion.addEventListener('click', function(e) {
var header = e.target.closest('.accordion-header');
if (!header) return;
var item = header.parentElement;
var isOpen = item.classList.contains('open');
// 关闭所有其他项
accordion.querySelectorAll('.accordion-item').forEach(function(otherItem) {
otherItem.classList.remove('open');
});
// 切换当前项
if (!isOpen) {
item.classList.add('open');
}
});
</script>
</body>
</html>示例3:样式操作性能对比
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>样式操作性能对比</title>
<style>
body { font-family: -apple-system, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
.test-box { width: 100px; height: 100px; background: #007bff; margin: 4px; display: inline-block; }
table { width: 100%; border-collapse: collapse; margin: 16px 0; }
th, td { padding: 8px 12px; text-align: left; border: 1px solid #ddd; }
th { background: #f5f5f5; }
button { padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; margin: 4px; }
</style>
</head>
<body>
<h1>样式操作性能对比</h1>
<p>对比不同样式修改方式的性能差异</p>
<button onclick="runPerformanceTest()">运行性能测试</button>
<div id="test-container" style="min-height:50px;"></div>
<table>
<thead>
<tr><th>方式</th><th>操作次数</th><th>耗时(ms)</th><th>说明</th></tr>
</thead>
<tbody id="perf-results"></tbody>
</table>
<script>
function runPerformanceTest() {
var container = document.getElementById('test-container');
var resultsBody = document.getElementById('perf-results');
resultsBody.innerHTML = '';
// 创建测试元素
container.innerHTML = '';
var elements = [];
for (var i = 0; i < 100; i++) {
var div = document.createElement('div');
div.className = 'test-box';
container.appendChild(div);
elements.push(div);
}
var iterations = 1000;
// 测试1:逐个设置style属性
var start = performance.now();
for (var iter = 0; iter < iterations; iter++) {
for (var i = 0; i < elements.length; i++) {
elements[i].style.backgroundColor = '#28a745';
elements[i].style.margin = '8px';
elements[i].style.borderRadius = '4px';
}
}
var time1 = (performance.now() - start).toFixed(2);
// 测试2:使用cssText
start = performance.now();
for (var iter = 0; iter < iterations; iter++) {
for (var i = 0; i < elements.length; i++) {
elements[i].style.cssText = 'background-color: #28a745; margin: 8px; border-radius: 4px;';
}
}
var time2 = (performance.now() - start).toFixed(2);
// 测试3:使用classList
// 先定义CSS类
var style = document.createElement('style');
style.textContent = '.test-style { background-color: #28a745 !important; margin: 8px !important; border-radius: 4px !important; }';
document.head.appendChild(style);
start = performance.now();
for (var iter = 0; iter < iterations; iter++) {
for (var i = 0; i < elements.length; i++) {
elements[i].classList.add('test-style');
elements[i].classList.remove('test-style');
}
}
var time3 = (performance.now() - start).toFixed(2);
// 测试4:使用CSS变量
start = performance.now();
for (var iter = 0; iter < iterations; iter++) {
for (var i = 0; i < elements.length; i++) {
elements[i].style.setProperty('--test-bg', '#28a745');
elements[i].style.removeProperty('--test-bg');
}
}
var time4 = (performance.now() - start).toFixed(2);
// 渲染结果
var results = [
{ method: '逐个style属性', time: time1, desc: 'style.prop = value' },
{ method: 'cssText', time: time2, desc: 'style.cssText = "..."(覆盖式)' },
{ method: 'classList', time: time3, desc: 'classList.add/remove(切换类名)' },
{ method: 'CSS变量', time: time4, desc: 'style.setProperty/removeProperty' }
];
results.forEach(function(r) {
var tr = document.createElement('tr');
tr.innerHTML = '<td>' + r.method + '</td><td>' + (iterations * 100) +
'</td><td>' + r.time + '</td><td>' + r.desc + '</td>';
resultsBody.appendChild(tr);
});
// 清理
container.innerHTML = '';
}
</script>
</body>
</html>浏览器兼容性
样式操作方法兼容性
classList兼容性写法
代码示例
// classList兼容性封装
function addClass(element, className) {
if (element.classList) {
element.classList.add(className);
} else {
if (!hasClass(element, className)) {
element.className += ' ' + className;
}
}
}
function removeClass(element, className) {
if (element.classList) {
element.classList.remove(className);
} else {
element.className = element.className.replace(
new RegExp('(^|\\s)' + className + '(\\s|$)'), ' '
).trim();
}
}
function toggleClass(element, className) {
if (element.classList) {
element.classList.toggle(className);
} else {
if (hasClass(element, className)) {
removeClass(element, className);
} else {
addClass(element, className);
}
}
}
function hasClass(element, className) {
if (element.classList) {
return element.classList.contains(className);
}
return new RegExp('(^|\\s)' + className + '(\\s|$)').test(element.className);
}注意事项与最佳实践
1. 减少重排和重绘
代码示例
// 不推荐:多次修改样式,可能触发多次重排
element.style.width = '100px';
element.style.height = '100px';
element.style.margin = '10px';
// 推荐1:使用cssText一次性设置
element.style.cssText = 'width: 100px; height: 100px; margin: 10px;';
// 推荐2:使用CSS类
element.className = 'styled-box';
// 推荐3:批量修改时先隐藏元素
element.style.display = 'none';
// ... 大量样式修改
element.style.display = '';
// 推荐4:使用requestAnimationFrame
requestAnimationFrame(function() {
element.style.transform = 'translateX(100px)';
});2. 优先使用CSS类而非直接修改样式
代码示例
// 不推荐:直接修改样式
element.style.backgroundColor = 'red';
element.style.color = 'white';
element.style.padding = '10px';
// 推荐:使用CSS类
// CSS: .error { background-color: red; color: white; padding: 10px; }
element.classList.add('error');
// 优点:
// 1. 关注点分离:样式在CSS中,逻辑在JS中
// 2. 可维护性:修改样式只需改CSS
// 3. 性能:切换类名比修改多个样式属性更高效
// 4. 可复用:同一类名可在多处使用3. 使用CSS变量实现动态主题
代码示例
// 推荐:使用CSS变量
document.documentElement.style.setProperty('--primary-color', '#ff6600');
// 不推荐:遍历所有元素修改样式
document.querySelectorAll('.btn').forEach(function(btn) {
btn.style.backgroundColor = '#ff6600';
});4. 获取元素尺寸的正确方式
代码示例
// 获取元素尺寸的几种方式
// 方式1:getComputedStyle(返回包含单位的字符串)
var width = getComputedStyle(element).width; // "300px"
// 方式2:getBoundingClientRect(返回数值,包含边框)
var rect = element.getBoundingClientRect();
console.log(rect.width); // 302(包含border)
console.log(rect.height); // 202
// 方式3:offsetWidth/offsetHeight(包含边框和滚动条)
console.log(element.offsetWidth); // 302
console.log(element.offsetHeight); // 202
// 方式4:clientWidth/clientHeight(不包含边框,包含padding)
console.log(element.clientWidth); // 300
console.log(element.clientHeight); // 200
// 方式5:scrollWidth/scrollHeight(包含溢出内容)
console.log(element.scrollWidth);
console.log(element.scrollHeight);代码规范示例
样式操作规范
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>样式操作规范</title>
<style>
/* 1. 使用CSS类定义样式状态 */
.is-active { background: #007bff; color: white; }
.is-hidden { display: none; }
.is-loading { opacity: 0.6; pointer-events: none; }
.is-disabled { opacity: 0.5; cursor: not-allowed; }
.has-error { border-color: #dc3545; }
.has-success { border-color: #28a745; }
</style>
</head>
<body>
<div id="app">
<button id="submit-btn" class="btn">提交</button>
</div>
<script>
(function() {
'use strict';
var btn = document.getElementById('submit-btn');
// 1. 使用CSS类切换状态(推荐)
btn.addEventListener('click', function() {
btn.classList.add('is-loading');
// 模拟异步操作
setTimeout(function() {
btn.classList.remove('is-loading');
btn.classList.add('has-success');
}, 2000);
});
// 2. 必须直接修改样式时,使用style属性
function setElementPosition(element, x, y) {
element.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
}
// 3. 使用CSS变量实现动态值
function setThemeColor(color) {
document.documentElement.style.setProperty('--primary-color', color);
}
// 4. 批量修改时使用cssText
function resetStyles(element) {
element.style.cssText = '';
}
// 5. 读取计算样式
function getActualWidth(element) {
return element.getBoundingClientRect().width;
}
})();
</script>
</body>
</html>常见问题与解决方案
问题1:style属性读取不到CSS类中的样式
症状: element.style.width 返回空字符串,但元素确实有宽度。
解决方案:
代码示例
// style属性只能读取内联样式
// CSS类中的样式需要使用getComputedStyle
// 错误方式
var width = element.style.width; // ""(空字符串)
// 正确方式
var width = getComputedStyle(element).width; // "300px"
// 或者使用offsetWidth
var width = element.offsetWidth; // 300(数值)问题2:classList在IE9及以下不支持
解决方案:
代码示例
// 使用前面的兼容性封装函数
// 或者使用className操作
// 添加类名
function addClass(el, cls) {
if (el.classList) {
el.classList.add(cls);
} else {
var classes = el.className.split(' ');
if (classes.indexOf(cls) === -1) {
classes.push(cls);
el.className = classes.join(' ');
}
}
}问题3:getComputedStyle返回的值带有单位
症状: 需要数值进行计算,但返回的是"300px"这样的字符串。
解决方案:
代码示例
// 方案1:使用parseFloat
var width = parseFloat(getComputedStyle(element).width); // 300
// 方案2:使用getBoundingClientRect
var rect = element.getBoundingClientRect();
var width = rect.width; // 300(数值)
var height = rect.height; // 200(数值)
// 方案3:使用offsetWidth/clientWidth
var width = element.offsetWidth; // 数值,包含border
var width = element.clientWidth; // 数值,不包含border问题4:CSS变量在IE中不支持
解决方案:
代码示例
// 方案1:直接修改元素样式
// 不使用CSS变量,直接设置样式
element.style.color = themeColor;
// 方案2:使用PostCSS插件将CSS变量编译为静态值
// 构建时处理,运行时无需CSS变量支持
// 方案3:使用polyfill
// 引入ie11-customproperties等polyfill库总结
DOM样式操作是实现动态交互效果的核心能力,掌握各种样式操作方法及其适用场景至关重要:
style属性:设置内联样式,CSS属性名需转为驼峰命名
cssText:一次性设置多个样式,适合批量修改但会覆盖已有内联样式
getComputedStyle:获取最终计算样式,包含所有来源的综合结果
classList:操作类名的最佳方式,提供add/remove/toggle/contains/replace方法
className:整体替换类名字符串,适合需要完全替换的场景
CSS变量:通过setProperty/getPropertyValue操作,实现动态主题
性能优化:优先使用CSS类、减少重排重绘、使用CSS变量替代遍历修改
遵循"样式在CSS中,逻辑在JS中"的原则,优先使用CSS类切换状态,能够编写出更高效、更可维护的代码。
常见问题
问题1:style属性读取不到CSS类中的样式?
症状: element.style.width 返回空字符串,但元素确实有宽度。 解决方案:
问题2:classList在IE9及以下不支持?
解决方案:
问题3:getComputedStyle返回的值带有单位?
症状: 需要数值进行计算,但返回的是"300px"这样的字符串。 解决方案:
问题4:CSS变量在IE中不支持?
解决方案:
本文由小确幸生活整理发布,转载请注明出处
本文涉及AI创作
内容由AI创作,请仔细甄别