批改状态:合格
老师批语:
本次简单选项卡主要是一个三选容器,当点击其中某个选项时,其他的选项会被覆盖。
html代如下:
<div class="tabs"><!-- 导航 --><ul class="tab"><li class="active" data-index="1">家事</li><li data-index="2">国事</li><li data-index="3">世事</li></ul><!-- details --><ul data-index="1" class="item active"><li><a href="">腊月完婚好开心</a></li><li><a href="">开始小新婚生活</a></li><li><a href="">开始造人小计划</a></li></ul><ul data-index="2" class="item"><li><a href="">疫情开始有转机</a></li><li><a href="">新年春运不停站</a></li><li><a href="">勤洗手讲究卫生</a></li></ul><ul data-index="3" class="item"><li><a href="">特朗普离职演讲</a></li><li><a href="">多国疫情再变异</a></li><li><a href="">丰田扩中国市场</a></li></ul></div>
对应css代码如下:
<style>* {margin: 0;padding: 0;box-sizing: border-box;}a {color: #555;text-decoration: none;}a:hover {color: red;text-decoration: underline;}li {list-style: none;line-height: 1.6rem;}li:hover {cursor: default;}.tabs {width: 300px;height: 300px;margin: 30px;background-color: #e6e6e6;display: flex;flex-direction: column;}.tab {display: flex;height: 36px;}.tab li {flex: auto;text-align: center;height: 36px;background-color: #fff;}.tab li.active {background-color: #e6e6e6;}.tab li:hover {cursor: pointer;}/* 默认所有选项卡只有一个显示,其它隐藏 */.item {padding: 20px;display: none;}/* .item和.active之间不能有空格 */.item.active {display: block;}</style>
js代码如下:
<script>const tab = document.querySelector(".tab");const items = document.querySelectorAll(".item");tab.onclick = (ev) => {// console.log(ev.target);// console.log(ev.currentTarget);//点中选项卡中任一个,先将所有选项卡active清空,然后再将找到触发对象设置active[...tab.children].forEach((item) => item.classList.remove("active"));ev.target.classList.add("active");//联动操作选项卡对应的新闻列表//同样要先清空所有item的active,通过ev触发对象data-index属性来找到对应item,然后添加activeitems.forEach((item) => {item.classList.remove("active");});//通过filter来找对应的新闻内容列表,添加active类属性[...items].filter((item) => item.dataset.index === ev.target.dataset.index)[0].classList.add("active");};</script>
总体上的思路:设置选项卡与对应的新闻列表的某个属性一致,如代码中的 ul.tab.li 和 下面的ul.item都会有一个相同自定义属性data-index,选中ul.tab.li时,通过其data-index属性找到其他的ul并设置为不显示(display:none) ,剩下ul设置为display:block;
解析:
当遇到页面上需要加载特别多的图片或者视频文件时,我们希望加载页面时,不要一次性将所有文件渲染到页面中,这样会浪费较多计算机的资源,我们希望当文件进入到用户视野时,再渲染文件,这样不仅灵活,也能节省计算机资源。
两个概念:
可视区高度:打开浏览器,在没有滚动条时,能加载内容的最大高度。
滚动高度:下拉进度条离可视区顶部的距离
所以什么情况下,文件算是进入到用户的视野
文件的顶部距离 < 可视区刻度+滚动高度
示范代码:
//假设html代码中添加了80张图片,<img src="images/temp.jpg" alt="" data-src="images/img-1.jpg" />。。。<img src="images/temp.jpg" alt="" data-src="images/img-80.jpg" />
js代码:
控制当文件的顶部距离<可视区高度+滚动高度时,用自定义属性data-src的属性值替代原有src属性值,同时为了不让图片显示比较突兀,还通过setTimeout来让图片在0.5秒后开始加载。由于高度数据在不断变化,所以需要给window添加监听器。
<script>const imgs = document.querySelectorAll(".container img");const clientHeight = document.documentElement.clientHeight;window.addEventListener("scroll", layzyload);// load:页面加载完成自动执行window.addEventListener("load", layzyload);function layzyload() {// 滚动高度let scrollTop = document.documentElement.scrollTop;// 遍历图片并判断是否进入到了可视区imgs.forEach((img) => {// 只要当前图片距离文档顶部的偏移量,小于可视区高度与滚动高度之间则表示进入到可视区,应该显示出来// clientHeight是可视区高度,这是一个固定的值,滚动高度是动态的if (img.offsetTop < clientHeight + scrollTop) {setTimeout(() => (img.src = img.dataset.src), 500);}});}</script>
我们希望实现的轮播图,如京东等购物网站首页
- 图片下方有一组小按钮,能够指定显示图上;
- 在图片的两侧分别有一个箭头,可以实现上一张和下一张浏览
- 鼠标事件,当鼠标移出轮播图区域时,图片以两秒的间隔进行轮播
html代码:
<div class="container" ><!-- 1 图片组 --><nav class="imgs"><img src="../../21/0111/banner/banner1.jpg" alt="" class="active" data-index="1" /><img src="../../21/0111/banner/banner2.jpg" data-index="2" alt="" /><img src="../../21/0111/banner/banner3.jpg" data-index="3" alt="" /><img src="../../21/0111/banner/banner4.jpg" data-index="4" alt="" /></nav><!-- 2 按钮组 --><nav class="btns"><!-- 不直接定义按钮数量,根据图片数据生成 --></nav><!-- 3. 翻页 --><nav class="skip"><a href="#" class="prev"><</a><a href="#" class="next">></a></nav></div>
css代码:
* {margin: 0px;padding: 0px;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.active {background-color: #000;}.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;}
js代码:
<script>// 所有图片const imgs = document.querySelectorAll(".container > .imgs img");// 按钮组const btnGroup = document.querySelector(".container > .btns");// 翻页按钮const skip = document.querySelectorAll(".container > .skip > a");// 方法1:获取图片数量生成对应的按钮组,遍历时每次插入一个a标签// imgs.forEach((img, i = 0) => {// let btnHtml = `<a href="#" data-index="${i + 1}"></a>`;// if (i === 0)// btnHtml = `<a href="#" class="active" data-index="${i + 1}"></a>`;// console.log(btnHtml);// btns.insertAdjacentHTML("beforeEnd", btnHtml);// i++;// });// 方法2:函数,创建一个文件片断,先创建对应数量的a标签,再统一将文件片断添加到对应的btnGroup里面function autoCreateBtns(ele, imgLength) {const frag = document.createDocumentFragment();for (let i = 0; i < imgLength; i++) {let a = document.createElement("a");a.href = "#";a.dataset.index = i + 1;if (i === 0) a.classList.add("active");frag.appendChild(a);}ele.appendChild(frag);}// 调用函数,传入按钮组和图片数量到btnGroupautoCreateBtns(btnGroup, imgs.length);//思考:要求1中按钮组事件与要求2翻页按钮具有共性,假设具有active类属性的对象为显示状态,不具有active类属性的对象显示隐藏,那么当我们触发一个事件时,都需要将某一个集合的对象全部移除active属性,同时将需要将某个集合中的指定元素添加acitve类属性,所以这里可以写三个公共函数://全部移除active属性function removeActive(ele){[...ele].forEach((item) => item.classList.remove("active"));}//弹出集合中中具有active属性的对象function getActiveEle(ele) {let activities = [...ele].filter((item) =>item.classList.contains("active"));return activities.shift();}//将指定元素Index添加active属性,其余去掉active属性function setActiveEle2(ele, index) {[...ele].forEach((item) => {if (item.dataset.index == index) {item.classList.add("active");} else {item.classList.remove("active");}});//要求1:图片下方有一组小按钮,能够指定显示图上btns.forEach((btn) =>btn.addEventListener("click", (ev) => {removeActiveEle([...btns]);removeActiveEle([...imgs]);setActiveEle2([...btns], ev.target.dataset.index);setActiveEle2([...imgs], ev.target.dataset.index);}));//要求2. 在图片的两侧分别有一个箭头,可以实现上一张和下一张浏览//思路:当时没到尽头时,图片直接显示index-1就行,到尽头时,需要跳转到另一端的尽头//简化:这里面都是非黑即白的判断,前一张或者后一张,到尽头还是没到尽头,可以用三元运算符来简化代码skip.forEach((item) =>item.addEventListener("click", (ev) => {let previndex = getActiveEle(imgs).dataset.index - 1;let nextindex = parseInt(getActiveEle(imgs).dataset.index) + 1;if (ev.target.className == "prev") {if (previndex != 0) {//没到尽头,直接显示previndexremoveActiveEle([...btns]);removeActiveEle([...imgs]);setActiveEle2([...imgs], previndex);setActiveEle2([...btns], previndex);} else {//到尽头,直接跳转另一端的尽头removeActiveEle([...btns]);removeActiveEle([...imgs]);setActiveEle2([...imgs], 4);setActiveEle2([...btns], 4);}} else if (ev.target.className == "next") {if (nextindex != 5) {//没到尽头,直接显示nextindexremoveActiveEle([...btns]);removeActiveEle([...imgs]);setActiveEle2([...imgs], nextindex);setActiveEle2([...btns], nextindex);} else if (nextindex == 5) {//到尽头,直接跳转另一端的尽头removeActiveEle([...btns]);removeActiveEle([...imgs]);setActiveEle2([...imgs], 1);setActiveEle2([...btns], 1);}}}));//要求3. 鼠标事件,当鼠标移出轮播图区域时,图片以两秒的间隔进行轮播//思考:自动事件setInterval,图片第2秒跳转,类似于每2秒点击一次后一张的按钮事件//定时器let clock = null;//定义点击事件类型const clickEvent = new Event("click");//获取容器区域const container = document.qureySelector(".container");//点击对象const autonext = document.querySelector(".skip .next");//鼠标移出就开始定时轮播图片,定义start方法定时方法function start(){clock = setInteval(function(){//每2秒需要触发一次的事件类型为点击事件类型autonext.dispatchEvent(clickEvent);},2000);}//鼠标移出就停止定时器function stop(){clearInterval(clock);}//最后,将事件添加到容器对应的鼠标移出onmouseout和鼠标移入onmouerover事件监听器中container.addEventListener("mouseout",stop);container.addEventListener("mouseover",start);
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号