流式布局与懒加载的实现

14、js实现流式布局及重排列、懒加载。

先来看看效果

在这里插入图片描述

流式布局实现思路:

​ 其实流式布局咱可以参考百度的图片搜索。其实原理几个固定宽度的div列表,然后将子div或者img插入列表

具体插入哪个列表呢? 可以通过比较列表的高度,将子元素插入到列表高度最小的一个列表。

难点:

​ 其实没什么难点,获取数据,然后插入到列表中


懒加载实现思路

​ 就是根据滚动条的高度来判断是否到达底部。然后继续加载数据

难点:

  • 获取滚动条位置
    • document.documentElement.scrollTop || document.body.scrollTop
  • 获取滚动条的总高度
    • HTMLELement.scrollHeight
  • 获取页面总高度
    • document.documentElement.clientHeight|| document.body.clientHeight
  • 加载数据
    • 按照流式布局加载子元素的方法加进去就好了

优化点:

  1. 可以不必在滚动条完全到达底部在加载数据,可以在距离底部适当高度的时候就加载数据,可以让用户少些等待 时间

流式布局重排列

重排列? 就是当窗口大小发生变化的时候将流式布局重新进行布局。

​ 实现思路:可以将所有子元素存在一个数组中,然后监听窗口大小变化,达到一定变化程度的时候就进行重排列。(需要动态判断流式布局列的数量)

具体代码如下

<!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>流式布局及懒加载</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .container{
            display: flex;
            justify-content: space-around;
            /* 使每个容器保持自身的高度 */
            align-items: flex-start;
        }
        .default-width{
            width: 180px;
            margin: 0 5px;
            color: white;
            text-align: center;
            /* line-height: 56px; */
            font-size: 20px;
            /* border: 1px solid black; */
        }
        .default-width div{
            margin: 10px 0;
        }
        .btn{
            padding: 4px 8px;
            position: fixed;
            left: 50%;
        }
        .loading{
            /* display: none; */
            height: 50px;
            border: 1px solid black;
            text-align: center;
            line-height: 50px;
        }

        .load{
            display: block;
            background-color: red;
            height: 5px;
            width: 5px;
        }
    </style>
</head>
<body>
    <div class="container">
    </div>
    <script>
        var body = document.body
        var container = document.querySelector(".container");
        // child's id
        var id = 1
        // 存入多个列表
        var lists = [];
        // 所有列表的子元素
        var childrens = []
        // 将list添加至list
        var len = childrens.length
        
        // 初始化
        initLists()
        generateChild(60)

        // 计算list个数
        function initLists(){
            // 初始化前首先获取屏幕宽高 生成对应个list
            var initWidth = document.documentElement.clientWidth || document.body.clientWidth
            console.log('initWidth', initWidth);
            // 判断生成多少个list, list width is 180px ,left and rignt margin is 5px
            let n = Math.floor(initWidth / (180 + 10))
            // 多余宽度
            let bodyPadding = (initWidth - n * (180 + 10))/2
            body.style.padding = `0 ${bodyPadding}px`
            // 优化
            // if(initWidth < 800) body.style.minWidth = initWidth + "px"
            console.log('min-width', body.style.minWidth);
            // 生成list-div
            for (let i = 0; i < n; i++) {
                let div = document.createElement("div");
                div.className = "default-width"
                // div.innerText = i + 1
                container.append(div)
                lists.push(div)
            }
        }

        // 移除list
        function removeLists(){
            for (let k = 0; k < lists.length; k++) {
                container.removeChild(lists[k])
            }
        }

        // 绑定窗口大小改变事件
        window.onresize = debounce(()=>{
            console.log("尺寸改变了, 子元素数量", len);
            // 移除list DOM
            removeLists()
            // 清除lists 数组
            lists = []
            // 重新计算list
            initLists()
            // 子元素重排列
            generateChild(0)
        }, 300)
        
        // 监听滚动条
        window.onscroll = throttle(verdictScroll, 300)

        // 判断是否滚动条是否在最底部
        function verdictScroll(){
            // 滚动条总高度
            let scrollHeight = container.scrollHeight
            // console.log('总高度', scrollHeight);

            // 兼容获取scrollTop  document.documentElement.scrollTop || document.body.scrollTop
            // 获取scroll当前的位置
            let scrollTop = Math.ceil(document.documentElement.scrollTop || document.body.scrollTop)
            // console.log('当前高度', scrollTop);
            let clientHeight = document.documentElement.clientHeight || document.body.clientHeight
            // console.log('clientHeight', clientHeight);

            //  + 550 最大高度 提前加载数据
            if(clientHeight + scrollTop + 550 >= scrollHeight){
                console.log("滚动条触发新增");
                setTimeout(() => {
                    let co = lists.length * 10
                    generateChild(co)
                }, Math.random() * 100);
            }
        }

        // 节流函数
        function throttle(cb, timeout){
            let flag = false
            return function(){
                if(flag) return
                flag = true
                setTimeout(() => {
                    cb()
                    flag = false
                }, timeout);
            }
        }
        
        //防抖
        function debounce(cb, timeout){
            let timer = null
            return function(){
                if(timer) clearTimeout(timer)
                timer = setTimeout(() => {
                    cb()
                }, timeout);
                
            }
        }
        
        // 生成child 并添加至list
        function generateChild(count = 1){
            for (let i = 0; i < count; i++) {
                // 生成child
                let child = document.createElement("div")
                // 获取随机样式
                let {h,r,g,b} = randomChildStyle()
                // 添加样式
                child.style.height = h + "px"
                child.style.backgroundColor = `rgb(${r}, ${g}, ${b})`
                child.innerText = "id:" + id++ 
                // 将元素存入childrens
                childrens.push(child)
                // 存入某个元素之前
                // minHeightOuter.insertBefore(child, innerLoading)
            }
            len = childrens.length
            // 将childrens推入list
            let j
            if(count !== 0){
                for ( j = len - count; j < len; j++) {
                    // 获取最小高度div
                    let minHeightOuter = getMinHeightOuter(lists)
                    // 添加至dom元素
                    minHeightOuter.append(childrens[j])   
                }
            }else{
                // 如果为0 则进行重排列
                for ( j = 0; j < len; j++) {
                    // 获取最小高度div
                    let minHeightOuter = getMinHeightOuter(lists)
                    // 添加至dom元素
                    minHeightOuter.append(childrens[j])   
                }
                console.log('重排列');             
            }
            console.log(`新增${count}`);
        }

        // 获取最小高度div 返回最小Height 的 DOM
        function getMinHeightOuter(doms){
            let minHeightDom = null

            for (let i = 0; i < doms.length; i++) {
                // 这里通过div的style获取height是获取不到的 因为div的style属性为空
                // heightArr[i] = doms[i].offsetHeight
                if(minHeightDom !== null){
                    // 寻找高度最低的那个outer
                    if(minHeightDom.offsetHeight > doms[i].offsetHeight){
                        minHeightDom = doms[i]
                    }
                }else{
                    // 初始化 minHeightDom
                    minHeightDom = doms[i]
                }
            }
            return minHeightDom
        }

        // 获取div随机样式 颜色、高度
        function randomChildStyle(){
            let h = Math.random() * 200 + 50
            let r = Math.random() * 255
            let g = Math.random() * 255
            let b = Math.random() * 255
            return {
                h,r,g,b
            }
        }

    </script>
</body>
</html>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值