滚动加载插件.手撸实战

// github L6zt
滚动插件设计原理

  1. 获取滚动元素的视口高度viewH和滚动高度scrollH,得出 滚动轴最大滚动距离 scrollMaxTop = viewH – scrollH;
  2. 根据滚动时计算滚动时滚动轴的滚动高度 scrollTop 与 scrollMaxTop, 比较做差,判断是否触发动作。
  3. 加入节流函数->优化性能。
  4. 借鉴过饿了vue滚动指令
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .item {
            height: 20px;
            background: black;
            margin-bottom: 20px;
        }
        .view {
            height: 100px;
            overflow: auto;
        }
    </style>
</head>
<body>
<div class="view">
</div>
</body>
<script src="./jquery.js"></script>
<script>
    // 节流函数
    let uuid = 1;
    const thrFn = ({
                       fn,
                       time,
                       maxTime
                   }) => {
        let timeK = null;
        let oTime = (new Date()).getTime();
        const execFn = function () {
            fn.apply(null, arguments);
            oTime = (new Date()).getTime();
        }
        return function() {
            const nTime = (new Date).getTime();
            let args = arguments;
            clearTimeout(timeK);
            if (nTime - oTime > maxTime) {
                execFn.call(null, ...args);
            } else {
                timeK = setTimeout(() => {
                    execFn.call(null, ...args)
                }, time);
            }
        }
    }
    const scroll = ({
                        container = window, // 滚动容器
                        fn, //触发加载时 回调函数
                        triggerT = 50, // 触发距离
                        time = 100, // 节流函数 
                        maxTime = 200, // 节流函数 最大触发时间
                        immediate = false,// 初始化后是否 直接触发回调函数。
                        loadingHtml = '<div class="ee-loading" style="padding: 20px; font-size: 16px; text-align: center">加载中</div>'
                    }) => {
        const $elem = $(container);
        const elem = $elem.get(0);
        const $elemT = (elem === window ? $(window) : $elem);
        // 初始化高度
        let startY = 0;
        const $loading = $(loadingHtml);
        // 是否显示loading
        const showLoading = (flag) => {
            const $container = elem === window ? $('body') : $elem;
            if (flag === true) {
                $container.append($loading);
            } else {
                $loading.remove();
            }
        }
        // 监听
        const fixFn = thrFn({
            fn,
            time,
            maxTime
        });
        // 获取元素滚动轴 距离容器顶部高度
        const MakeScrollTop = (elem) => {
            return () => {
                if (elem === window) {
                    return window.pageYOffset || window.document.documentElement.scrollTop
                }
                return elem.scrollTop
            }
        };
        // 获取 元素滚动高度
        const scrollHeight = (elem) => {
            if (elem === window) {
                return window.document.documentElement.scrollHeight || window.document.body.scrollHeight
            }
            return elem.scrollHeight
        }
        // 设置元素 滚动轴距离 顶部高度
        const setScrollTop = (y) => {
            if (elem === window) {
                window.pageYOffset = window.document.documentElement.scrollTop = y;
                return
            }
            elem.scrollTop = y;
        }
        const getScrollTop = MakeScrollTop(elem);
        const eventFn = () => {
            // 当前滚动距离
            let currentY = getScrollTop();
            // 当前容器真实高度
            let height = $elem.height();
            // console.log(height);
            // 当前容器最大滚动距离
            let allY = scrollHeight(elem) - height;
            // 方向判断 触发版判断
            if (currentY - startY > 0 && allY - currentY <= triggerT) {
                fixFn(showLoading, currentY);
            }
            startY = currentY;
        }
        $elemT.on('scroll', eventFn);
        const offScroll = () => {
            $elemT.off('scroll', eventFn);
        }
        immediate && fn(showLoading, 0);
        return {
            offScroll,
            setScrollTop
        }
    };
    // 使用代码
    const htmlTemplate = `<div class="item">num</div>`
    const list = new Array(8).fill(true);
    let time = 0;
    let busy = false;
    const fn = function(load, y) {
        console.log(y);
        if (busy === false) {
            busy = true;
            load(true);
            setTimeout(() => {
                load(false)
                busy = false;
                time++;
                const str = list.map(item => htmlTemplate).join('').replace(/num/g, time);
                $('.view').append(str);
            }, 2000)
        }
    };
    const handler = scroll({
        container: $('.view'),
        fn,
        immediate: true
    })
</script>
</html>

demo地址

    原文作者:L6zt
    原文地址: https://segmentfault.com/a/1190000015961583
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞