一、封装 win 方法

  • 获取或者设置浏览器的窗口的盒模型属性:
  1. let winW = document.documentElement.clientWidth || document.body.clientWidth;
  2. let winH = document.documentElement.clientHeight || document.body.clientHeight;
  • 因为获取浏览器的窗口的盒子模型属性都需要兼容写法,为了提高效率封装一个方法;
  1. function win(attr, val) {
  2. if (typeof val !== "undefined") {
  3. // 传2个值的时候是设置,传一个值是获取
  4. document.documentElement[attr] = document.body[attr] = val;
  5. }
  6. return document.documentElement[attr] || document.body[attr];
  7. }
  8. console.log(win('scrollTop'));
  9. console.log(win('screenTop', 1000));

二、跑马灯

  • html代码
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. * {
  8. margin: 0;
  9. padding: 0;
  10. }
  11. .box {
  12. width: 800px;
  13. height: 200px;
  14. overflow: hidden;
  15. border: 1px dashed deeppink;
  16. margin: 40px auto;
  17. }
  18. .box ul {
  19. height: 200px;
  20. }
  21. .box ul li {
  22. float: left;
  23. width: 200px;
  24. height: 200px;
  25. overflow: hidden;
  26. }
  27. .box ul li img {
  28. width: 100%;
  29. height: 100%;
  30. }
  31. .clearfix:after {
  32. display: block;
  33. content: '';
  34. height: 0;
  35. visibility: hidden;
  36. clear: both;
  37. }
  38. </style>
  39. </head>
  40. <body>
  41. <div class="box">
  42. <ul class="ulBox clearfix" id="ulBox">
  43. <li><img src="./img/1.jpg" alt=""></li>
  44. <li><img src="./img/2.jpg" alt=""></li>
  45. <li><img src="./img/3.jpg" alt=""></li>
  46. <li><img src="./img/4.jpg" alt=""></li>
  47. </ul>
  48. </div>
  49. <script src="1-跑马灯.js"></script>
  50. </body>
  51. </html>
  • js代码
  1. let ul = document.querySelector('#ulBox');
  2. let box = document.querySelector('.box');
  3. ul.innerHTML += ul.innerHTML; // 为了实现无缝轮播需要把 ul 里面的所有 li 复制一份放到 ul 中;
  4. ul.style.width = '1600px';
  5. let timer = setInterval(() => {
  6. box.scrollLeft += 1;
  7. if (box.scrollLeft >= 800) {
  8. // 当满足这个条件时,说明此时正好滚出去 4 个 li,在 box 里展示的正是我们复制出来的 4 个 li,这个时候需要把 box.scrollLeft 设置成 0,但是因为设置成 0 时展示的也是这 4 张图片,给人的感觉好像没有换,所以还是无缝的轮播的
  9. box.scrollLeft = 0;
  10. }
  11. }, 10);

三、计算生效的样式

1. ele.style (可读可写)只能获取或者设置行内样式

  1. let box = document.getElementById('box');
  • 获取、设置元素的样式
  1. box.style.xxx
  2. box.style.xxx = xxx;

2. 获取浏览器最终计算生效后的样式

  • window.getComputedStyle() 方法用于获取元素对象经计算生效后的样式;
  • 语法:window.getComputedStyle(元素对象, 伪类)
  • 如果不需要伪类:window.getComputedStyle(元素对象, null) 不需要写伪类时,第二个参数写null
  • 返回值:一个对象,对象中包含该元素所有的样式,并且该对象是 CSSStyleDeclaration 的实例
  • 获取元素样式
  1. let styles = window.getComputedStyle(box, null);
  2. console.log(styles);
  3. console.log(styles.width); // 200px
  4. console.log(styles.height); // 300px
  5. console.log(styles.marginTop); // 10px css 连字符样式需要使用驼峰命名法
  6. console.log(styles['margin-top']); // 10px 不用驼峰命名法需要这样写
  • 获取伪类样式:
  1. let fakeStyles = window.getComputedStyle(box, 'before');
  2. console.log(fakeStyles);
  3. console.log(fakeStyles.content); // hello
  4. console.log(fakeStyles.color); // rgb(0, 255, 255)
  5. console.log(fakeStyles.height); // auto
  • IE 低版本 6-8 不支持这个语法
  • IE中有的元素对象获取计算过的生效的样式:
  • 元素对象.currentStyle 属性,该属性是一个对象,上面记录这个该元素生效的样式
  • 获取生效的样式:
    标准浏览器下: window.getComputedStyle 方法;window.getComputedStyle(元素对象, 伪类) 返回一个对象
    IE浏览器下:元素对象.currentStyle 属性; 该属性值是一个对象,里面存储了该元素所有的样式

3. 封装getCss方法,并且处理单位和IE兼容

  1. // 优化:去除单位、同一 透明度样式:
  2. function getCss(ele, attr) {
  3. var value;
  4. if ('getComputedStyle' in window) {
  5. value = window.getComputedStyle(ele, null)[attr];
  6. } else {
  7. // 判读获取的属性是否是透明度,如果是需要给IE的透明度属性进行特殊处理
  8. if (attr === 'opacity') {
  9. value = ele.currentStyle['filter'];
  10. var reg2 = /^alpha\(opacity=(.+)\)$/;
  11. value = reg2.exec(value)[1] / 100;
  12. } else {
  13. value = ele.currentStyle[attr];
  14. }
  15. }
  16. // 去除单位: 只有是数字带单位的情况下才需要去除单位
  17. var reg = /^-?\d+(\.\d+)?(px|pt|rem|em)$/i;
  18. if (reg.test(value)) {
  19. value = parseFloat(value);
  20. }
  21. }
  22. console.log(getCss(box, 'width'));
  23. console.log(getCss(box, 'opacity'));

四、图片懒加载

图片延时加载(图片懒加载)

真实项目中,为了提升页面的加载速度,我们一般将图片处理成延时加载;

  • 效果:
    页面中的图片在页面刚刚打开时,浏览器会立刻去请求这张图片资源。但是延时加载是页面打开时,不是立刻去加载图片,而是在某个合适的时机去加载这张图片(一般是图片进入浏览器可视区域或者即将进入可视区域);
  • 原理:
    img 标签有一个 src 属性,值是这张图片的资源路径;只要浏览器检测到 img 有这个属性就会立刻去加载,为了实现延时加载,不直接给 img 标签设置 src 属性,而是选择自定义其他属性保存其图片资源路径;等到何时的时机,再获取这个自定义属性值,再赋值给图片的 src 属性,此时,浏览器会根据这个 src 去加载图片。

1. 单张图片延时加载

  • 单张图片延时加载:
  • 时机:图片即将进入浏览器可视窗口
  • 监听页面的滚动事件,当页面滚动时,计算图片什么时候进入可视窗口;
  • 进入浏览器可视窗口条件:(图片上外边距离页面顶端的距离 - 浏览器的可视窗口的高度 - 页面纵向滚动条卷去的距离) <= 0
  • html:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. * {
  8. margin: 0;
  9. padding: 0;
  10. }
  11. .top {
  12. width: 500px;
  13. margin: 0 auto;
  14. height: 1000px;
  15. border: 10px solid #00b38a;
  16. }
  17. .img-wrapper {
  18. width: 500px;
  19. min-height: 200px;
  20. border: 1px solid #000;
  21. margin: 100px auto;
  22. }
  23. </style>
  24. </head>
  25. <body>
  26. <div id="top" class="top">
  27. 这个盒子就是用来占位的,我是一个很长很长的盒子
  28. </div>
  29. <div class="img-wrapper">
  30. <img data-src="img/1.jpg" alt="" id="first">
  31. </div>
  32. <div class="img-wrapper">
  33. <img data-src="img/2.jpg" alt="">
  34. </div>
  35. <div class="img-wrapper">
  36. <img data-src="img/3.jpg" alt="">
  37. </div>
  38. <script src="js/utils.js"></script>
  39. <script src="js/3-多张图片延时加载.js"></script>
  40. </body>
  41. </html>
  1. // 1. 获取该图片
  2. let singleImg = document.querySelector('#first');
  3. // 2. 获取浏览器可视窗口的高度
  4. let winH = utils.win('clientHeight');
  5. // 3. 监听 window 的 onscroll 事件,在事件函数中计算图片是否进入浏览器的可视窗口
  6. window.onscroll = function () {
  7. // 1. 获取图片的自定义属性保存的图片资源路径
  8. let dataSrc = singleImg.getAttribute('data-src');
  9. // 2. 获取当前页面滚动条卷去的高度
  10. let winScrollTop = utils.win('scrollTop');
  11. // 3. 获取图片的上外边框距离页面顶部的距离;
  12. let imgOffsetTop = utils.offset(singleImg).top;
  13. // 4. 判断图片是否进入浏览器的可是窗口
  14. if (imgOffsetTop - winH - winScrollTop <= 0) {
  15. // 满足这个条件说明图片即将或者已经进入了可视窗口,此时给 img 的 src 赋值
  16. singleImg.src = dataSrc;
  17. }
  18. };

优化

真实项目中,因为网络或者其他因素可能导致图片加载失败,所以一般不是直接给图片赋值,而是先动态创建一个 img 标签,用动态创建的 img 去尝试加载,如果加载成功就再给页面中的图片 src 属性赋值。

  1. // 1. 获取该图片
  2. let singleImg = document.querySelector('#first');
  3. // 2. 获取浏览器可视窗口的高度
  4. let winH = utils.win('clientHeight');
  5. // 3. 监听 window 的 onscroll 事件,在事件函数中计算图片是否进入浏览器的可视窗口
  6. window.onscroll = function () {
  7. // 1. 获取图片的自定义属性保存的图片资源路径
  8. let dataSrc = singleImg.getAttribute('data-src');
  9. // 2. 获取当前页面滚动条卷去的高度
  10. let winScrollTop = utils.win('scrollTop');
  11. // 3. 获取图片的上外边框距离页面顶部的距离;
  12. let imgOffsetTop = utils.offset(singleImg).top;
  13. // 4. 判断图片是否进入浏览器的可是窗口
  14. if (imgOffsetTop - winH - winScrollTop <= 0) {
  15. // 满足这个条件说明图片即将或者已经进入了可视窗口,此时给 img 的 src 赋值
  16. // 4.1 动态创建 img
  17. let newImg = document.createElement('img');
  18. // 4.2 尝试加载
  19. newImg.src = dataSrc;
  20. // 4.3 监听临时图片的 onload 事件,如果加载成功会触发这个事件
  21. newImg.onload = function () {
  22. singleImg.src = dataSrc;
  23. newImg = null; // 手动释放内存
  24. }
  25. }
  26. };

多张图片延时加载

  • 多张图片延时加载:
  • 获取页面中所有的图片(或者某个容器元素下的所有需要延时加载的图片),
  • 监听页面中 onscroll 事件,在事件函数中,计算每张图片的是否即将出现在浏览器的可视窗口中
  • 如果当前图片即将进入,就进行该图片的加载。在加载之前需要判断该图片是否有 src 属性,如果有了 src 属性,说明该图片已经加载过了,不需要重新加载
  1. // 1. 获取图片集合
  2. let imgList = document.querySelectorAll('img');
  3. // 2. 获取当前浏览器可视窗口的高度
  4. let winH = utils.win('clientHeight');
  5. // 3. 监听窗口的滚动事件
  6. window.onscroll = function () {
  7. // 3.1 获取当前页面滚动条卷去的高度
  8. let winSctp = utils.win('scrollTop');
  9. // 3.2 遍历图片集合,在遍历过程中计算每张图片是否进入可视区域
  10. for (let i= 0; i < imgList.length; i++) {
  11. let imgItem = imgList[i];
  12. if (imgItem.src) continue; // 如果图片的 src 属性存在且不为空,说明该图片已经加载过了,后面的加载不需要再执行了
  13. let imgOffsetTop = utils.offset(imgItem).top;
  14. let dataSrc = imgItem.getAttribute('data-src');
  15. if (imgOffsetTop - winH - winSctp <= 0) {
  16. let newImg = new Image(); // 新建图片,等效于 document.createElement('img')
  17. newImg.src = dataSrc;
  18. newImg.onload = function () {
  19. imgItem.src = dataSrc;
  20. newImg = null;
  21. }
  22. }
  23. }
  24. };