LazyLoadEle - 延迟加载页面元素的Jquery扩展

原创
2021/02/25 13:24
阅读数 112

LazyLoadEle - 延迟加载页面元素的Jquery扩展

业务需要,需要在元素进入视窗后增加统计,找了一圈没有发现现成的工具库,那就自己动手干吧

代码陆续改了两次, 增加了 filterHistoryBind 参数用于 控制是否要过滤掉已绑定过的元素, 增加这个参数的原因是页面上有瀑布流数据,当有增量的dom数据时,原有的dom会被重复绑定的风险.

代码如下:

// lazyloadEle Author: echo丨.info
(function (root, factory) {
    if (typeof exports === "object") {
        module.exports = factory(root);
    } else if (typeof define === "function" && define.amd) {
        define([], factory);
    } else {
        root.LazyLoadEle = factory(root);
    }
}) (typeof global !== "undefined" ? global : this.window || this.global, function (root) {

    "use strict";

    if (typeof define === "function" && define.amd){
        root = window;
    }

    const defaults = {
        selector: ".v-lazyload-ele",
        root: null,
        rootMargin: "0px",
        threshold: 0,
        filterHistoryBind: false, // 是否过滤掉已绑定的元素
		evtFunc: function (ele) {
			console.log('visible: ', ele)
        }
    };

    /**
     * Merge two or more objects. Returns a new object.
     * @private
     * @param {Boolean}  deep     If true, do a deep (or recursive) merge [optional]
     * @param {Object}   objects  The objects to merge together
     * @returns {Object}          Merged values of defaults and options
     */
    const extend = function ()  {

        let extended = {};
        let deep = false;
        let i = 0;
        let length = arguments.length;

        /* Check if a deep merge */
        if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") {
            deep = arguments[0];
            i++;
        }

        /* Merge the object into the extended object */
        let merge = function (obj) {
            for (let prop in obj) {
                if (Object.prototype.hasOwnProperty.call(obj, prop)) {
                    /* If deep merge and property is an object, merge properties */
                    if (deep && Object.prototype.toString.call(obj[prop]) === "[object Object]") {
                        extended[prop] = extend(true, extended[prop], obj[prop]);
                    } else {
                        extended[prop] = obj[prop];
                    }
                }
            }
        };

        /* Loop through each object and conduct a merge */
        for (; i < length; i++) {
            let obj = arguments[i];
            merge(obj);
        }

        return extended;
    };

    function LazyLoadEle(eles, options) {
        this.settings = extend(defaults, options || {});
        this.eles = eles || document.querySelectorAll(this.settings.selector);

        this.observer = null;
        this.init();
    }

    LazyLoadEle.prototype = {
        init: function() {

            /* Without observers load everything and bail out early. */
            if (!root.IntersectionObserver) {
                this.loadDataList();
                return;
            }

            let self = this;
            let observerConfig = {
                root: this.settings.root,
                rootMargin: this.settings.rootMargin,
                threshold: [this.settings.threshold]
            };

            this.observer = new IntersectionObserver(function(entries) {
                Array.prototype.forEach.call(entries, function (entry) {
                    if (entry.isIntersecting) {
                        self.observer.unobserve(entry.target);
                        self.settings.evtFunc(entry.target)
                    }
                });
            }, observerConfig);

            Array.prototype.forEach.call(this.eles, function (ele) {

                if (self.settings.filterHistoryBind) {
                    if (jQuery(ele).hasClass('v-lazyload-ele-yes')) {
                        return true;
                    }
                }

                self.observer.observe(ele);

                jQuery(ele).addClass('v-lazyload-ele-yes');
            });
        },

        loadAndDestroy: function () {
            if (!this.settings) { return; }
            this.loadDataList();
            this.destroy();
        },

        loadDataList: function () {
            if (!this.settings) { return; }

            let self = this;
            Array.prototype.forEach.call(this.eles, function (ele) {
                if (self.settings.filterHistoryBind) {
                    if (jQuery(ele).hasClass('v-lazyload-ele-yes')) {
                        return true;
                    }
                }

                self.settings.evtFunc(ele);

                jQuery(ele).addClass('v-lazyload-ele-yes');
            });
        },

        destroy: function () {
            if (!this.settings) { return; }
            this.observer.disconnect();
            this.settings = null;

            Array.prototype.forEach.call(this.eles, function (ele) {
                jQuery(ele).removeClass('v-lazyload-ele-yes');
            });
        }
    };

    root.lazyloadEle = function(eles, options) {
        return new LazyLoadEle(eles, options);
    };

    if (root.jQuery) {
        const $ = root.jQuery;
        $.fn.lazyloadEle = function (options) {
            options = options || {};
            new LazyLoadEle($.makeArray(this), options);
            return this;
        };
    }

    return LazyLoadEle;
});
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
1
分享
返回顶部
顶部