批改状态:合格
老师批语:
1.className属性可以用来设置元素的类(class)值或返回元素的class属性值。
obj.className = classNameValue;
<style>.red {color: red;}.bg {background-color: #ff0;}</style><p>Hello World!</p>
现在有一个p标签,我想把文字的颜色和背景色替换一下,可以这样操作:
<script>const p = document.querySelector('p');p.className = "red bg";</script>

如果想要读取p元素的class属性值,也可以使用className属性:
console.log(p.className); // red bg
2.classList属性值可以获取元素的类名,用于为元素添加、移除、切换CSS类名。
length:统计元素类名称的个数。
<p class="red bg">Hello World!</p><script>console.log(p.classList.length); // 2</script>
| 方法名称 | 解释说明 |
|---|---|
| add(class1,class2,…) | 向元素添加类名,如果添加的类名已经存在,则不添加 |
| remove(class1,class2,…) | 移除元素指定的类名,如果该类名不存在,则会报错 |
| toggle(className, boolean) | 切换元素的类名,如果要切换的类名不存在,则会自动向元素里添加这个类名。第二个为可选参数,布尔值用于设置元素是否强制添加或移除类,不管该类名是否存在。 |
| contains(class) | 判断指定的类名是否存在。存在返回true,不存在返回false |
p.classList.add("green");p.classList.remove("red");p.classList.toggle('red1');p.classList.contains('red1'));
读取HTML元素上的用户自定义属性,使用dataset属性。
element.dataset.className
<p id="aaa" data-email="admin@admin.com" data-my-age="90" data-index="1">我的资料</p>
以上定义了个p元素,如果需要获取id值,可以直接使用:
console.log(p.id); // aaa
若是想要获取data-eamil的属性值,就不能使用p.data-email了,这个用法是错误的,需要使用dataset属性:
console.log(p.dataset.email); // admin@admin.com
如果需要获取data-my-age属性该怎么办呢?此时,就需要使用驼峰式的方法来获取:
console.log(p.dataset.myAge); // 90
自定义属性必须是以“data-”开头的;
如果要获取自定义的属性,需要去掉前缀“data-”;
在获取的属性值的时候如果需要带(-)的属性值需要转成驼峰式的写法。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>选项卡</title><link rel="stylesheet" href="./static/css/tabs.css"></head><body><div class="box"><!-- tabs --><ul class="tabs"><li class="tab active" data-index="1">综合新闻</li><li class="tab" data-index="2">官方新闻</li><li class="tab" data-index="3">赛事新闻</li><li class="tab" data-index="4">更新日志</li></ul><!-- panels --><ul class="panels"><li class="panel active" data-index="1"><div class="panel-lists"><a class="recommend" href="#"><h3>完美世界电竞将主办DPC中国区比赛 1月18日举行线下开幕式及揭幕战</h3><div class="contents"><div class="item-avatar"><img src="https://img.dota2.com.cn/dota2/63/c5/63c52fb6846974b76797c433064a23fa1609475659.jpg" alt="完美世界电竞将主办DPC中国区比赛 1月18日举行线下开幕式及揭幕战"></div><div class="msg"><p>全球DOTA2玩家期待已久的DPC即将开启,很荣幸地宣布完美世界电竞将主办中国区联赛,全球六大赛区将同步启动。</p><span class="date">2021年01月12日</span></div></div></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2绝品龙钩,竟能够在嘉年华一键领取?</p><span class="p_date">2021-01-11</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2 1月11日更新日志:7.28b平衡性更新</p><span class="p_date">2021-01-11</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>PC定级赛DAY2赛况:Aster力克RNG,率先杀入S级联赛!</p><span class="p_date">2021-01-10</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2展区谍照曝光:探秘Roshan巢穴,与军团决斗</p><span class="p_date">2021-01-08</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>没有人给你评级,你来为你自己定级!DPC中国联赛定级赛今日开战</p><span class="p_date">2021-01-08</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2 1月8日更新日志:技能征召更新</p><span class="p_date">2021-01-08</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>DPC中国联赛定级赛1月8日11:00开战 谁能进入S级联赛?</p><span class="p_date">2021-01-07</span></a></div></li><li class="panel" data-index="2"><div class="panel-lists"><a class="recommend" href="#"><h3>完美世界电竞将主办DPC中国区比赛 1月18日举行线下开幕式及揭幕战</h3><div class="contents"><div class="item-avatar"><img src="https://img.dota2.com.cn/dota2/63/c5/63c52fb6846974b76797c433064a23fa1609475659.jpg" alt="完美世界电竞将主办DPC中国区比赛 1月18日举行线下开幕式及揭幕战"></div><div class="msg"><p>全球DOTA2玩家期待已久的DPC即将开启,很荣幸地宣布完美世界电竞将主办中国区联赛,全球六大赛区将同步启动。</p><span class="date">2021年01月12日</span></div></div></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2绝品龙钩,竟能够在嘉年华一键领取?</p><span class="p_date">2021-01-11</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2 1月11日更新日志:7.28b平衡性更新</p><span class="p_date">2021-01-11</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>PC定级赛DAY2赛况:Aster力克RNG,率先杀入S级联赛!</p><span class="p_date">2021-01-10</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2展区谍照曝光:探秘Roshan巢穴,与军团决斗</p><span class="p_date">2021-01-08</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>没有人给你评级,你来为你自己定级!DPC中国联赛定级赛今日开战</p><span class="p_date">2021-01-08</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2 1月8日更新日志:技能征召更新</p><span class="p_date">2021-01-08</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>DPC中国联赛定级赛1月8日11:00开战 谁能进入S级联赛?</p><span class="p_date">2021-01-07</span></a></div></li><li class="panel" data-index="3"><div class="panel-lists"><a class="recommend" href="#"><h3>完美世界电竞将主办DPC中国区比赛 1月18日举行线下开幕式及揭幕战</h3><div class="contents"><div class="item-avatar"><img src="https://img.dota2.com.cn/dota2/63/c5/63c52fb6846974b76797c433064a23fa1609475659.jpg" alt="完美世界电竞将主办DPC中国区比赛 1月18日举行线下开幕式及揭幕战"></div><div class="msg"><p>全球DOTA2玩家期待已久的DPC即将开启,很荣幸地宣布完美世界电竞将主办中国区联赛,全球六大赛区将同步启动。</p><span class="date">2021年01月12日</span></div></div></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>DPC定级赛DAY2赛况:Aster力克RNG,率先杀入S级联赛!</p><span class="p_date">2021-01-10</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2 1月11日更新日志:7.28b平衡性更新</p><span class="p_date">2021-01-11</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>PC定级赛DAY2赛况:Aster力克RNG,率先杀入S级联赛!</p><span class="p_date">2021-01-10</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2展区谍照曝光:探秘Roshan巢穴,与军团决斗</p><span class="p_date">2021-01-08</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>没有人给你评级,你来为你自己定级!DPC中国联赛定级赛今日开战</p><span class="p_date">2021-01-08</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2 1月8日更新日志:技能征召更新</p><span class="p_date">2021-01-08</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>DPC中国联赛定级赛1月8日11:00开战 谁能进入S级联赛?</p><span class="p_date">2021-01-07</span></a></div></li><li class="panel" data-index="4"><div class="panel-lists"><a class="recommend" href="#"><h3>完美世界电竞将主办DPC中国区比赛 1月18日举行线下开幕式及揭幕战</h3><div class="contents"><div class="item-avatar"><img src="https://img.dota2.com.cn/dota2/d0/27/d027f043743b5127a9afaf5a2f5730191610354489.jpg" alt="DOTA2 1月11日更新日志:7.28b平衡性更新"></div><div class="msg"><p>全球DOTA2玩家期待已久的DPC即将开启,很荣幸地宣布完美世界电竞将主办中国区联赛,全球六大赛区将同步启动。</p><span class="date">2021年01月12日</span></div></div></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2绝品龙钩,竟能够在嘉年华一键领取?</p><span class="p_date">2021-01-11</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2 1月11日更新日志:7.28b平衡性更新</p><span class="p_date">2021-01-11</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>PC定级赛DAY2赛况:Aster力克RNG,率先杀入S级联赛!</p><span class="p_date">2021-01-10</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2展区谍照曝光:探秘Roshan巢穴,与军团决斗</p><span class="p_date">2021-01-08</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>没有人给你评级,你来为你自己定级!DPC中国联赛定级赛今日开战</p><span class="p_date">2021-01-08</span></a><a class="p_list" href="#"><i class="p_icon p_icon_dot"></i><p>DOTA2 1月8日更新日志:技能征召更新</p><span class="p_date">2021-01-08</span></a><a class="p_list p_highlight" href="#"><i class="p_icon p_icon_dot"></i><p>DPC中国联赛定级赛1月8日11:00开战 谁能进入S级联赛?</p><span class="p_date">2021-01-07</span></a></div></li></ul></div><script>console.log(document.documentElement);const tabs = document.querySelector('.tabs');// 卡盘导航const tabsNum = document.querySelectorAll('.tabs > *');console.log(tabsNum);// 内容列表const panels = document.querySelectorAll('.panel');console.log(panels);tabs.addEventListener('click', ev => {// 事件触发对象(事件绑定者)console.log(ev.currentTarget);// 事件触发者console.log(ev.target.classList.item[0]);// 激活点击的对象只需要两步:// 1.清空之前所有处于激活状态的选项卡,并将当前点击的对象激活console.log(tabs.children);[...tabs.children].forEach(tab => tab.classList.remove('active'));ev.target.classList.add('active');// 2.根据自定义的属性data-index找到对应的列表并显示出来panels.forEach(panels => panels.classList.remove('active'));// console.log([...panels].filter(item => item.dataset.index === ev.target.dataset.index));// filter返回的是一个数组,因此需要:[...panels].filter(item => item.dataset.index === ev.target.dataset.index)[0].classList.add('active');});</script></body></html>

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>一键换肤</title><style>.container {width: 300px;display: grid;grid-template-columns: repeat(6, 1fr);column-gap: 10px;}.container > img {width: 100%;border: 3px solid #ffffff;}body {width: 100%;height: 100%;background: url('./static/images/1.jpg') no-repeat scroll 0 0;background-size: cover;}</style></head><body><div class="container"><img src="./static/images/1.jpg" alt=""><img src="./static/images/2.jpg" alt=""><img src="./static/images/3.jpg" alt=""><img src="./static/images/4.jpg" alt=""><img src="./static/images/5.jpg" alt=""><img src="./static/images/6.jpg" alt=""></div><script>let clientW = window.screen.width;let clientH = window.screen.height;console.log(clientW, clientH);console.log(document.body);document.body.style.width = clientW;document.body.style.height = clientH;const container = document.querySelector('.container');container.onclick = ev => {console.log(ev.currentTarget);console.log(ev.target);document.body.style.backgroundImage = `url(${ev.target.src})`;}</script></body></html>
如果当前图片距离文档顶部的高度(偏移量) < 文档可视区 + 滚动高度,则表示图片进入到可视区,需要将图片加载出来。
1.元素距离文档顶部的偏移量
let offsetTop = ele.offsetTop;
2.文档可视区高度
let clientHeight = document.documentElement.clientHeight;
3.滚动高度
let scrollTop = document.documentElement.scrollTop;
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>懒加载原理</title></head><body><img src="./static/images/1.jpg" width="1000" alt="" data-src="./static/images/2.jpg"><script>// 视口高度let clientHeight = document.documentElement.clientHeight;// 滚动高度const img = document.querySelector('img');console.log(img);let scrollTop = document.documentElement.scrollTop;window.onscroll = ev => {if (img.offsetTop < clientHeight + document.documentElement.scrollTop) {img.src = img.dataset.src;}}</script></body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>轮播图片</title><style>/* 初始化 */* {margin: 0;padding: 0;box-sizing: border-box;}a {text-decoration: none;}/* 轮播图的容器 */.container {width: 62.5em;height: 22em;margin: 1em auto;/* 转为定位元素/定位父级 */position: relative;}/* 图片组 */.container>.imgs img {width: 100%;height: 100%;/* 默认全部隐藏 */display: none;/* 将所有的图片进行绝对定位,确保每一次只看到一张,所有图片共享这个容器 */position: absolute;left: 0;top: 0;}/* 设置默认显示的图片(第一张) */.container>.imgs img.active {display: block;}/* 按钮组(独立按钮) */.container>.btns {position: absolute;left: 0;right: 0;bottom: 0;/* 水平居中 */text-align: center;}.container>.btns a {/* 转成行内块元素: 即能水平排列,双支持宽度设置 */display: inline-block;padding: 0.5em;margin: 0 0.2em;background-color: #fff;border-radius: 50%;}.container>.btns a.active {background-color: #000;}/* 翻页按钮 */.container .skip a {position: absolute;width: 2.5rem;height: 5rem;line-height: 5rem;text-align: center;opacity: 0.3;top: 9rem;font-weight: lighter;font-size: 2rem;background-color: #ccc;}.container .skip .prev {left: 0;}.container .skip .next {right: 0;}.container .skip *:hover {opacity: 0.6;color: #666;}</style></head><body><div class="container"><!-- 1. 图片组 --><nav class="imgs"><a href=""><img src="./static/images/banner/banner1.jpg" alt="" data-index="1" class="active" /></a><a href=""><img src="./static/images/banner/banner2.jpg" alt="" data-index="2" /></a><a href=""><img src="./static/images/banner/banner3.jpg" alt="" data-index="3" /></a><a href=""><img src="./static/images/banner/banner4.jpg" alt="" data-index="4" /></a></nav><!-- 2. 图片小按钮 --><nav class="btns"></nav><!-- 3. 翻页 --><nav class="skip"><a href="#" class="prev"><</a><a href="#" class="next">></a></nav></div><script src="./static/js/banner.js"></script></body></html>
JS代码
// 获取所有图片const imgs = document.querySelectorAll('.container .imgs img');console.log(imgs);// 获取所有的按钮const btnsGroup = document.querySelector('.container > .btns');// 翻页按钮const skips = document.querySelectorAll('.container > .skip');console.log(skips);// 实际上,轮播图片中的小圆点是根据轮播图片的数量来进行创建的,图片数量 === 圆点数量// 创建一个文档片段,将生成的小圆点一次性添加到文档中。const frag = document.createDocumentFragment();for (let i = 0; i < imgs.length; i++) {const a = document.createElement('a');a.href = "#";a.dataset.index = i + 1;// 默认激活第一个元素i === 0 ? a.classList.add('active') : '';frag.appendChild(a);}btnsGroup.appendChild(frag);/*** 获取激活的图片* @param {obj} ele 元素对象*/function getActiveEle (ele) {let active = [...ele].filter(img => img.classList.contains('active'))return active.shift();}console.log(getActiveEle(imgs));// 获取刚刚生成的小按钮const btns = document.querySelectorAll('.container .btns > *');console.log(btns);// 1.获取激活的元素btns.forEach(btn => {btn.addEventListener('click', ev => setActiveEle(ev.target));});/*** 设置激活的元素active* @param {obj} ele 元素*/function setActiveEle(ele) {[imgs, btns].forEach(item => {// 获取激活状态的图片和圆点按钮let activeEle = [...item].filter(ele => ele.classList.contains('active')).shift();// 清除所有的active状态的元素activeEle.classList.remove('active');console.log(activeEle);item.forEach(arr => {console.log(arr);if (arr.dataset.index === ele.dataset.index) {arr.classList.add('active');}});});}// 获取翻页按钮const prev = document.querySelector('.prev');const next = document.querySelector('.next');prev.addEventListener('click', ev => {let activeEle = [...imgs].filter(item => item.classList.contains('active'));console.log(typeof activeEle[0].dataset.index); //// 获取当前激活元素的索引值let activeElemIndex = activeEle[0].dataset.index;console.log("1.当前索引值为:", activeElemIndex);// 如果当前的激活元素的索引值(index)为1,那么图片就是第一张,再次点击prev按钮,会调到最后一张图if (activeElemIndex === '1') {console.log('1111');setActiveEle(Array.from(imgs)[imgs.length - 1]);activeElemIndex = [...imgs].filter(item => item.classList.contains('active'))[0].dataset.index;console.log("2.当前索引值为:", activeElemIndex);} else {setActiveEle(Array.from(imgs)[activeElemIndex - 2]);}});// 如果当图片处于最后一张时,点击next按钮应该调到第一张,即:激活第一张图next.addEventListener('click', ev => {// 获取当前激活的图片let activeEle = [...imgs].filter(img => img.classList.contains('active'));// 获取当前图片的索引值if (Number(getActiveEleIndex(activeEle)) === imgs.length) {setActiveEle(Array.from(imgs)[0]);} else {setActiveEle(Array.from(imgs)[getActiveEleIndex(activeEle)]);}});/*** 获取激活状态下的元素的索引值(index)* @param {obj} ele 处于激活状态下的元素*/function getActiveEleIndex(ele) {return ele[0].dataset.index;}

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号