美文网首页
懒加载的模块化实现

懒加载的模块化实现

作者: upup_dayday | 来源:发表于2018-07-09 04:09 被阅读0次

    问题背景:

    有时打开一个页面,要很长时间页面才能响应,这是因为通常对于页面响应的JS,需要等待页面的元素上全部加载完毕后,才能执行;
    图片加载需要的时间都比较长,对于图片较多的页面设计,如果不对元素进行设置的话,就需要将所有图片加载完后,页面才能响应
    这不仅花费时间较长;同时也会浪费流量,可能用户并不需要看后面的许多内容;

    懒加载就是针对这种情况的一个解决方法,对于页面上的元素,当进入视野中才进行加载,这样就减少了页面打开加载的时间,同时也节省了不必要的流量。
    对于一些需要实时更新内容的元素,也可利用懒加载,在元素进入视野时,再刷新;

    场景模拟:

    模拟一个场景,既需要加载图片也需要实时更新页面内容


    image.png

    上半部是需要实时更新文本的部分,每当文本框进入视野时,文本内容会更新;
    下方是需要加载的多个图片

    1.模块化的实现

    页面中不同的模块需要的处理方式不同,文本信息重新进入视野需要刷新内容;但图片即便多次翻动页面进入视野,也不需要重复加载,只需要一次就够了;
    所以,为了更好的模块兼容性,使用面向对象的方法来实现懒加载的模块,针对不同的需求,只需要进行相应的实例化,就可以了

    function showImg($node) {
        $node.attr('src', $node.attr('data-src'))
    }
    
    var Lazy = (function() {
                return {
                    realTime: function($targets, callback) {
                        $targets.each(function(idx, target) {
                            new Exposure($(target), false, callback);
                        })
                    },
    
                    once: function($targets, callback) {
                        $targets.each(function(idx, target) {
                            new Exposure($(target), true, callback);
                        })
                    }
                }
            })()
    
            Lazy.realTime($('#hello'), function($node) {
                $node.text($node.text() + '123');
            });
            Lazy.realTime($('#world'), function($node) {
                $node.text($node.text() + '456');
            });
            Lazy.once($('.container img'), function($node) {
                showImg($node);
            });
    
      function Exposure($target, once_check, callback) {
            this.$target = $target;
            this.once_check = once_check;
            this.callback = callback;
            this.loaded = false;
            this.bind();
            this.check();
    }
    

    对于不同的模块,通过不同的接口进行实例化,并提供相应的回调来处理模块进入视野后的处理方法;
    值得说明的一点是,Lazy提供的接口中,是利用了数组的方法.each,来对每个元素都进行了一次Exposure的对象创建。
    这是考虑到对于批量的图片,只需要一次全部选择,即可对内部每一个图片进行实例化了,使用更方便,即便是内部只有一个元素的文本,也可通用,兼容性更好。但缺点是对象的重复创建太多,每个img都创建了一个Exposure对象

    2.模块进入视野的判断方法

            Exposure.prototype.isVisible = function($node) {
                var windowHeight = $(window).height();
                var offsetTop = $node.offset().top;
                var nodeHeight = $node.height();
                var scrollTop = $(window).scrollTop();
                if (windowHeight + scrollTop > offsetTop + nodeHeight && scrollTop < offsetTop + nodeHeight) {
                    return true
                }
    
                return false
            }
    

    滚动的高度加上窗口的高度,大于目标到页面顶端的高度,说明进入窗口。
    同时,滚动高度小于目标到页面的offsetTop,说明还停留在窗口中,没出去,两个条件都要满足

    3.判断元素是否加载过

            Exposure.prototype.isLoaded = function($node) {
                if ($node.attr('loaded')) {
                    return true;
                } else {
                    $node.attr('loaded', 'true');
                    return false;
                }
            }
    

    通过判断元素属性“loaded”,来判断元素是否加载过

    源码
    演示
    可以看到,当反复滚动页面,文本框重新进入窗口后,文本内容改变
    在showImg中console.log,在控制台可以看到,当图片加载过一次之后,再滚动页面,load-img-go不再增加

    image.png

    相关文章

      网友评论

          本文标题:懒加载的模块化实现

          本文链接:https://www.haomeiwen.com/subject/gvnauftx.html