写现懒加载的实现原理,并代码实例演示
* 可视区高度: 用户可以看到的窗口高宽,通常小于文档高度
* 滚动距离: 有滚动条的情况下,元素滚动条顶部到窗口顶部的距离
* 自定义属性: data-为前缀的自定义元素属性
* 滚动事件`scroll`: 当窗口滚动时触动发
* 加载事件`load`: 当html文档与资源全部加载完成时触发实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>懒加载</title> </head> <body style="height: 2000px"> <script> var container=document.createElement('div'); container.setAttribute('align','center'); // 创建文档片段, 可以理解为保存在内存中的页面中的小组件 // createdocumentfragment()方法创建了一虚拟的节点对象,节点对象包含所有属性和方法。 var frag=document.createDocumentFragment(); // 页面中的图片,我们全部动态创建,使用文档片段提升加载效率 for(var i=1;i<=8;i++){ var imgUrl='images/'+i+'.jpg'; var img=document.createElement('img'); // 设置统一显示的占位图片 img.setAttribute('src','images/loading.gif'); // 将真实的图片地址保存到自定义属性data-src中 img.setAttribute('data-src',imgUrl); // 自定义图片样式 img.setAttribute('style','width:600px;height:300px;margin:5px;'); // 先把图片添加到文档片段中, 因为是在内存中操作, 不会引起页面抖动,也不会触发大量的DOM操作 frag.appendChild(img); } // 将保存在文档片段中的所有图片添加到容器中 container.appendChild(frag); // 再把容器,插入到页面的唯一元素<script>之前 document.body.insertBefore(container,document.body.firstElementChild); // 监听窗口的滚动事件, 当用户拉到滚动条时, 自动触发自定义的图片懒加载事件方法 window.addEventListener('scroll',lazyLoaded,false); // 自定义懒加载事件方法 function lazyLoaded() { // documentElement 属性可返回文档的根节点。<html> // console.log(document.documentElement);//获取<html> // 获取滚动高度 var scrollTop=document.documentElement.scrollTop; // 可视区高度 var clientHeight=document.documentElement.clientHeight; // 图片懒加载 // 获取所有图片,并转为数组 var imgs = document.images; var imgArr=Array.prototype.slice.call(imgs,0); // 遍历所有图片,确定哪些需要显示出来 imgArr.forEach(function (img) { // 关键步骤: 当图片进入到窗口可视区时需要显示出来 // 图片顶部的距离如果小于可视区高度与可视区滚动距离之和时,说明已进入可视区 if(img.offsetTop<=(scrollTop+clientHeight)){ // 设置img真实的src图片地址,并显示出来 img.setAttribute('src',img.dataset.src); } }); } // 发现首次显示的时候,没有图片被加载,需要再添加一个load事件的监听器 // load: 当页面加载完成会自动调用 window.addEventListener('load',lazyLoaded,false); </script> </body> </html>
运行实例 »点击 "运行实例" 按钮查看在线实例
运行结果:
2. 写出选项卡的实现原理, 并代码实例演示
* 自定义属性: 标签页与详情页通过`data-index`建立关联
* classList: 优雅的操作元素的类样式
* forEach(): 优雅的遍历数组对象,注意参数是一个回调函数
实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>选项卡</title> <style> ul,li{ margin: 0; padding: 0; list-style: none; } a{ text-decoration: none; } a:hover{ color: red; text-decoration-color: red; text-decoration-line:underline ;/*underline 定义文本下的一条线。*/ } .tab-container{ width: 450px; height: 300px; } .tab-nav{ /*清浮动*/ overflow: hidden; } .tab-nav ul li{ float: left; width: 150px; height: 60px; line-height: 60px; text-align: center; font-size: 1.2rem; } .tab-nav .active{ background-color: lightblue; border-bottom: 1px solid red; } .tab-content .detail{ line-height: 35px; min-height: 200px; padding: 20px 10px; display: none; } .tab-content .detail.active{ background-color: lightblue; display: block; } </style> </head> <body> <div class="tab-container"> <!-- tab标签导航--> <div class="tab-nav"> <ul> <li class="active" data-index="1">HTML/CSS</li> <li data-index="2">JavaScript</li> <li data-index="3">服务端</li> </ul> </div> <!-- tab标签对应的内容--> <div class="tab-content"> <div class="detail active" data-index="1"> <ul> <li><a href="">HTML</a></li> <li><a href="">CSS</a></li> <li><a href="">LayUI</a></li> </ul> </div> <div class="detail" data-index="2"> <ul> <li><a href="">JavaScript</a></li> <li><a href="">jQuery</a></li> <li><a href="">Ajax</a></li> </ul> </div> <div class="detail" data-index="3"> <ul> <li><a href="">PHP</a></li> <li><a href="">Java</a></li> <li><a href="">C++</a></li> </ul> </div> </div> </div> <script> // 获取标签页导航tab,以及可点击的所有标签页<li>,并转为数组对象 var tabnav=document.getElementsByClassName('tab-nav')[0]; // console.log(tabnav.firstElementChild.children); //获取导航tab的所有li标签 var tabList=tabnav.firstElementChild.children; var tabArr=Array.prototype.slice.call(tabList,0); // 获取所有详情页,并转为数组对象 var detail=document.getElementsByClassName('detail'); var detailArr=Array.prototype.slice.call(detail,0); // 利用事件冒泡机制, 将标签页tab的点击事件委托给父级导航条处理 tabnav.addEventListener('click',showDetail,false); // 监听标签tab点击事件 function showDetail(event) { //event.target: 当前被点击的li, event.currentTarget: 被添加的事件的对象,<div.tab_nav> // console.log(event.target); // console.log(event.currentTarget); // 1. 清空原导航标签的样式,并设置当前正在被点击的标签页为当前页 tabArr.forEach(function (tab) { tab.classList.remove('active'); }); event.target.classList.add('active'); // 2. 清空所在详情页样式,并根据与导航data-index属性的对应关系,显示对应的详情页面 detailArr.forEach(function (detail) { detail.classList.remove('active'); }); detailArr.forEach(function (detail) { // 详情页的index与导航标签的index相同时, 显示该页面 if(detail.dataset.index===event.target.dataset.index){ detail.classList.add('active'); } }); } // 还可以添加鼠标移入监听事件 // tabnav.addEventListener('mouseover',showDetail,false); </script> </body> </html>
运行实例 »
点击 "运行实例" 按钮查看在线实例
运行结果: