瀑布流+懒加载

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了瀑布流+懒加载相关的知识,希望对你有一定的参考价值。

参考技术A 你们是否见过漂亮的照片墙呢?对,就是那种照片大小不一,看似不整齐但却有一定的排版,反而让人有一种赏阅感。其实在这美妙的背后,想要做一个照片墙出来,还需要用到懒加载。那有伙伴可能就要问了,什么是懒加载,你之前也没提到过呀,是的我确实没有讲过,但是哈我有说过预加载,懒加载无非就是一次性加载的照片多一点而已,让图片在可视区加载,即仅加载可以看到的区域,监控滚动条实现,设置超过一定值时又加载图片,相比较预加载,懒加载可以优化前端性能,减少请求数或延迟请求数,减少服务器的压力,那么接下来就由我来说说吧。

深度剖析-class的几个对象(utlis,component)-瀑布流-懒加载(概念,作用,原理,实现步骤)

💦正因为生命有限,所以才显得更重要,正因为生命有限,所以才更应该努力不懈。💦

深度剖析

深度剖析-class的几个对象-瀑布流-懒加载-面向对象实现(多选按钮-单选按钮)

分析class的几个对象-瀑布流-懒加载-多选框-单选框

深度剖析component.js:组件类的功能

export default class Component 
    /* 一个实例属性 */
    elem;
    /* 传入一个HTML类型 */
    constructor(type) 
        /* 创建一个htmlElement */
        this.elem = document.createElement(type);
        this.elem.className = 'div1';
        this.elem.innerHTML = '我爱你'
        // document.body.appendChild(this.elem)
    

    /* 传入一个父容器标签名字字符串,将创造的htmlElement添加在父容器里之后 */
    appendTo(parent) 
        /* 判断字符串,获取其对应的元素对象 */
        if (typeof parent === 'string') parent = document.querySelector(parent)
        /* 给父元素对象后appendChild(实例属性) */
        parent.appendChild(this.elem);
        /* 并且返回这个父容器 */
        return parent;
    
    /* 实例方法,将创造的属性对象,插入某个父容器的document对象之前 */
    insertTo(parent, nextElement) 
        /* 判断其类型是否Wie字符串 ,获取其document对象*/
        if (typeof parent === 'string') parent = document.querySelector(parent);
        if (typeof nextElement === 'string') nextElement = document.querySelector(nextElement);
        /* 如果条件符合,将数据插入到nextElement之前 */
        if (parent instanceof HTMLElement && nextElement instanceof HTMLElement) 
            parent.insertBefore(this.elem, nextElement);
        
    

深度剖析Utils.js:设置样式和创建元素

/* 静态方法类名调用 */
export default class Utils 
    constructor() 
        /* 构造函数可以默认为空,实例化对象时不执行任何代码 */
    
    /* 传入一个css样式的代码字符串 */
    static setCSS(css) 
        /* 
            document.styleSheets.length 代表的是style样式的个数
            Array.from(document.styleSheets) 将多个style转为数组处理
            ![].some(item => item.ownerNode.id === 'defined') 寻找style样式的id属性中是否有一个defined        
        */
        /* 如果啥都没有,style上面也没有id默认值 */
        if (document.styleSheets.length == 0 || !Array.from(document.styleSheets).some(item => item.ownerNode.id === 'defined')) 
            /* 创建一个style标签 */
            var style = document.createElement('style');
            /* 将传进来的css字符串添加到style中 */
            style.innerHTML = css;
            /* 并给这个样式添加一个鉴别值 */
            style.id = 'defined';
            /* 并且将style标签添加入到hand中 */
            document.head.appendChild(style);
            return;
        
        /* 如果有一个样式的id默认值是:defined 找出这个样式*/
        var styleSheet = Array.from(document.styleSheets).find(item => item.ownerNode.id === 'defined')
        /* 将传进来的css字符串解析 按最后的分割,然后去掉空格,每一个样式通过数组来调用*/
        var arr = css.split(/(?<=\\)/).map(item => item.trim());
        /* 然后遍历数组添加这个将每一个css样式添加进去 */
        arr.forEach(item => 
            styleSheet.insertRule(item, styleSheet.cssRules.length)
        )
    
    /* 下面这块作为扩展看看就行,创建一个元素并返回,并插入到这个父容器里面 */
    static createElement(type, className, parent) 
        if (typeof parent === 'string') parent = document.querySelector(parent);
        var elem = document.createElement(type);
        if (className) elem.className = className;
        if (parent instanceof HTMLElement) parent.appendChild(elem)
        return elem;
    


瀑布流

💚瀑布流又称瀑布流式布局,是比较流行的一种网站页面布局方式。视觉表现为参差不齐的多栏布局。

  • 实现逻辑:

每次选择每列高度最低的一列插入图片

  • 这个思路需要注意几点:ul作为最外层的容器,宽度的设置Wie100%;list-style: none;
  • li需要float起来
  • 最后记得清除浮动

清除浮动常用样式

.clear::after
	content: "";
	display: block;
	visibility: hidden;
	height: 0;
	overflow: hidden;
	clear: both;

  • 第一步初始化,根据需求创建列数;查看是否渲染到页面
  • 第二步,作为图片加载,添加load事件,加载成功之后获取相应height

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
       ul
            width: 100%;
            margin: 0;
            padding: 0;
            list-style: none;
        
        li
            float: left;
            margin: 0;
        
        li img
            width: 98%;
        
        .clear::after
            content: "";
            display: block;
            visibility: hidden;
            height: 0;
            overflow: hidden;
            clear: both;
        
    </style>
</head>
<body>
    <ul class="clear"></ul>
    <!-- 设置外层盒子并且选择好样式 -->
    <script>
        const COL = 5;/* 设置为5列显示 */
        var ul;
        var i=2;
        init();
        /* 初始化 */
        function init()
            /* 获取ul对象,根据需求添加元素 */
            ul = document.querySelector('ul')
            /* 添加li条 根据需求可调整列数*/
            ul.innerHTML = Array(COL).fill(1).reduce(v=> v+`<li style='width:$100/COL%'></li>`,"");
            /* 执行图片加载 */
            loadImage(i);

        
        /* 加载图片 */
        function loadImage(i)
            var img = new Image();
            img.src = `./img/load/$i-.jpg`;
            /* 给img添加加载事件 */
            img.addEventListener("load",loadHandler);
        
        function loadHandler(e)
            /* 提示:注意的是这里的this,指的就是img对象 */
            /* 加载完之后执行次函数,卸载加载侦听 */
            this.removeEventListener("load",loadHandler);
            /*t.offsetHeight:每一个ul的子元素, ul.firstElementChild.offsetHeight:ul的第一个子元素 */
            /* 找出li最小的 Height 值*/
            var min = Array.from(ul.children).reduce((v,t)=>t.offsetHeight<v?t.offsetHeight :v,ul.firstElementChild.offsetHeight);
            /* 找出那个最小min的li */
            var li = Array.from(ul.children).find(t=>t.offsetHeight === min);
            /* 将this对象插入 */
            li.appendChild(this);
            /* 在这里就已经完成了一张图片的插入,现在考虑这个加载停止和继续加载 */
            /* ================================== */
            /* 变换i值 */
            i++;
            /* 如果超过79就停止执行 */
            if(i>79) return 
            /* 
                *   页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片
                *   只有通过javascript设置了图片路径,浏览器才会发送请求。
                *   继续执行加载函数
            */
            loadImage(i);
        


    </script>
</body>
</html>

懒加载

JavaScript中的懒加载——概念,作用,原理,实现步骤

  1. 什么是懒加载?
  • 懒加载也就是延迟(控制开关)加载。
  • 针对本案例的:我自己的理解就是当我的加载区域达到某个条件,触发开关,关闭图片加载,当通过滚动条对达到某一条件,又继续开始加载。这就是懒加载
    当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样就只需请求一次,俗称占位图),以后再理解可能情景不同
  • 只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。
  1. 为什么要使用懒加载?
  • 很多页面,内容很丰富,页面很长,图片较多,例如瀑布流。比如说各种商城页面。这些页面图片数量多,而且比较大,少说百来K,多则上兆。

  • 要是页面载入就一次性加载完毕。估计大家都会等到黄花变成黄花菜了。

  1. 懒加载的原理是什么?
  • 页面中的img元素,如果没有src属性,浏览器就不会发出请求去加载图片, 只有通过javascript设置了(改变了)图片路径,浏览器才会发送请求。
  • 第一种是纯粹的延迟加载,使用setTimeOut或setInterval进行加载延迟
  • 第二种是条件加载,符合某些条件,或触发了某些事件才开始异步加载。
  • 第三种是可视区加载,即仅加载用户可以看到的区域,这个主要由监控滚动条来实现,一般会在距用户看到某图片前一定距离遍开始加载,这样能保证用户拉下时正好能看到图片。
  1. 懒加载的实现步骤?

此案例就是对条件判断。
ul的高度大于当前视口高度的4倍+当前滚动条已过去的高度

5.懒加载的优点是什么?
页面加载速度快、可以减轻服务器的压力、节约了流量,用户体验好

6:懒加载代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
       ul
            width: 100%;
            margin: 0;
            padding: 0;
            list-style: none;
        
        li
            float: left;
            margin: 0;
        
        li img
            width: 98%;
        
        .clear::after
            content: "";
            display: block;
            visibility: hidden;
            height: 0;
            overflow: hidden;
            clear: both;
        
    </style>
</head>
<body>
    <ul class="clear"></ul>
    <!-- 设置外层盒子并且选择好样式 -->
    <script>
        const COL = 5;/* 设置为5列显示 */
        var ul;
        var i=2;
        init();
        /* 初始化 */
        function init()
            /* 获取ul对象,根据需求添加元素 */
            ul = document.querySelector('ul')
            /* 添加li条 根据需求可调整列数*/
            ul.innerHTML = Array(COL).fill(1).reduce(v=> v+`<li style='width:$100/COL%'></li>`,"");
            /* 执行图片加载 */
            loadImage(i);
            /* 添加滚轮事件,后面判断滚轮位置 */
            window.addEventListener('scroll',scrollHandler)

        
        /* 加载图片 */
        function loadImage(i)
            var img = new Image();
            img.src = `./img/load/$i-.jpg`;
            /* 给img添加加载事件 */
            img.addEventListener("load",loadHandler);
        
        function loadHandler(e)
            /* 提示:注意的是这里的this,指的就是img对象 */
            /* 加载完之后执行次函数,卸载加载侦听 */
            this.removeEventListener("load",loadHandler);
            /*t.offsetHeight:每一个ul的子元素, ul.firstElementChild.offsetHeight:ul的第一个子元素 */
            /* 找出li最小的 Height 值*/
            var min = Array.from(ul.children).reduce((v,t)=>t.offsetHeight<v?t.offsetHeight :v,ul.firstElementChild.offsetHeight);
            /* 找出那个最小min的li */
            var li = Array.from(ul.children).find(t=>t.offsetHeight === min);
            /* 将this对象插入 */
            li.appendChild(this);
            /* 在这里就已经完成了一张图片的插入,现在考虑这个加载停止和继续加载 */
            /* ================================== */
            // ul的高度大于当前视口高度的4倍+当前滚动条已过去的高度
            if(ul.offsetHeight>document.documentElement.clientHeight*4+document.documentElement.scrollTop) return;
            continueLoad();
        
        /* 滚轮事件函数 */
        function scrollHandler(e)
            // 当前滚动条+视口高度的2倍大于ul的高度时,比较下面还留有1视口高度时继续加载
            if(document.documentElement.scrollTop+document.documentElement.clientHeight*2>ul.offsetHeight) 
                continueLoad()
            

        
        /* 函数化编程 */
        function continueLoad()
            i++;
            if(i>79) i=2;    
            loadImage(i);
        

    </script>
</body>
</html>

以上是关于瀑布流+懒加载的主要内容,如果未能解决你的问题,请参考以下文章

深度剖析-class的几个对象(utlis,component)-瀑布流-懒加载(概念,作用,原理,实现步骤)

HTML+CSS+JS 瀑布流式布局(实现懒加载)

瀑布流网页布局+加载动画+固定加载页数

js实现瀑布流以及加载效果

ios 瀑布流怎么自动滚动到指定cell

vue 瀑布流实现